/* * GRUB -- GRand Unified Bootloader * Copyright (C) 2008 Free Software Foundation, Inc. * * GRUB is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GRUB is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GRUB. If not, see . */ #define FIXED_PROPS #define LZMA_BASE_SIZE 1846 #define LZMA_LIT_SIZE 768 #define LZMA_PROPERTIES_SIZE 5 #define kNumTopBits 24 #define kTopValue (1 << kNumTopBits) #define kNumBitModelTotalBits 11 #define kBitModelTotal (1 << kNumBitModelTotalBits) #define kNumMoveBits 5 #define kNumPosBitsMax 4 #define kNumPosStatesMax (1 << kNumPosBitsMax) #define kLenNumLowBits 3 #define kLenNumLowSymbols (1 << kLenNumLowBits) #define kLenNumMidBits 3 #define kLenNumMidSymbols (1 << kLenNumMidBits) #define kLenNumHighBits 8 #define kLenNumHighSymbols (1 << kLenNumHighBits) #define LenChoice 0 #define LenChoice2 (LenChoice + 1) #define LenLow (LenChoice2 + 1) #define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits)) #define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits)) #define kNumLenProbs (LenHigh + kLenNumHighSymbols) #define kNumStates 12 #define kNumLitStates 7 #define kStartPosModelIndex 4 #define kEndPosModelIndex 14 #define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) #define kNumPosSlotBits 6 #define kNumLenToPosStates 4 #define kNumAlignBits 4 #define kAlignTableSize (1 << kNumAlignBits) #define kMatchMinLen 2 #define IsMatch 0 #define IsRep (IsMatch + (kNumStates << kNumPosBitsMax)) #define IsRepG0 (IsRep + kNumStates) #define IsRepG1 (IsRepG0 + kNumStates) #define IsRepG2 (IsRepG1 + kNumStates) #define IsRep0Long (IsRepG2 + kNumStates) #define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax)) #define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits)) #define Align (SpecPos + kNumFullDistances - kEndPosModelIndex) #define LenCoder (Align + kAlignTableSize) #define RepLenCoder (LenCoder + kNumLenProbs) #define Literal (RepLenCoder + kNumLenProbs) #define out_size 8(%ebp) #define now_pos -4(%ebp) #define prev_byte -8(%ebp) #define range -12(%ebp) #define code -16(%ebp) #define state -20(%ebp) #define rep0 -24(%ebp) #define rep1 -28(%ebp) #define rep2 -32(%ebp) #define rep3 -36(%ebp) #ifdef FIXED_PROPS #define FIXED_LC 3 #define FIXED_LP 0 #define FIXED_PB 2 #define POS_STATE_MASK ((1 << (FIXED_PB)) - 1) #define LIT_POS_MASK ((1 << (FIXED_LP)) - 1) #define LOCAL_SIZE 36 #else #define lc (%ebx) #define lp 4(%ebx) #define pb 8(%ebx) #define probs 12(%ebx) #define pos_state_mask -40(%ebp) #define lit_pos_mask -44(%ebp) #define LOCAL_SIZE 44 #endif RangeDecoderBitDecode: #ifdef FIXED_PROPS leal (%ebx, %eax, 4), %eax #else shll $2, %eax addl probs, %eax #endif movl %eax, %ecx movl (%ecx), %eax movl range, %edx shrl $kNumBitModelTotalBits, %edx mull %edx cmpl code, %eax jbe 1f movl %eax, range movl $kBitModelTotal, %edx subl (%ecx), %edx shrl $kNumMoveBits, %edx addl %edx, (%ecx) clc 3: pushf cmpl $kTopValue, range jnc 2f shll $8, code lodsb movb %al, code shll $8, range 2: popf ret 1: subl %eax, range subl %eax, code movl (%ecx), %edx shrl $kNumMoveBits, %edx subl %edx, (%ecx) stc jmp 3b RangeDecoderBitTreeDecode: RangeDecoderReverseBitTreeDecode: movzbl %cl, %ecx xorl %edx, %edx pushl %edx incl %edx pushl %edx 1: pushl %eax pushl %ecx pushl %edx addl %edx, %eax call RangeDecoderBitDecode popl %edx popl %ecx jnc 2f movl 4(%esp), %eax orl %eax, 8(%esp) stc 2: adcl %edx, %edx popl %eax shll $1, (%esp) loop 1b popl %ecx subl %ecx, %edx /* RangeDecoderBitTreeDecode */ popl %ecx /* RangeDecoderReverseBitTreeDecode */ ret LzmaLenDecode: pushl %eax addl $LenChoice, %eax call RangeDecoderBitDecode popl %eax jc 1f pushl $0 movb $kLenNumLowBits, %cl addl $LenLow, %eax 2: movl 12(%esp), %edx shll %cl, %edx addl %edx, %eax 3: call RangeDecoderBitTreeDecode popl %eax addl %eax, %edx ret 1: pushl %eax addl $LenChoice2, %eax call RangeDecoderBitDecode popl %eax jc 1f pushl $kLenNumLowSymbols movb $kLenNumMidBits, %cl addl $LenMid, %eax jmp 2b 1: pushl $(kLenNumLowSymbols + kLenNumMidSymbols) addl $LenHigh, %eax movb $kLenNumHighBits, %cl jmp 3b WriteByte: movb %al, prev_byte stosb incl now_pos ret /* * int LzmaDecode(CLzmaDecoderState *vs, * const unsigned char *inStream, * unsigned char *outStream, * SizeT outSize); */ _LzmaDecodeA: pushl %ebp movl %esp, %ebp subl $LOCAL_SIZE, %esp #ifndef ASM_FILE pushl %esi pushl %edi pushl %ebx movl %eax, %ebx movl %edx, %esi pushl %ecx #else pushl %edi #endif cld #ifdef FIXED_PROPS movl %ebx, %edi movl $(Literal + (LZMA_LIT_SIZE << (FIXED_LC + FIXED_LP))), %ecx #else movl $LZMA_LIT_SIZE, %eax movb lc, %cl addb lp, %cl shll %cl, %eax addl $Literal, %eax movl %eax, %ecx movl probs, %edi #endif movl $(kBitModelTotal >> 1), %eax rep stosl popl %edi xorl %eax, %eax movl %eax, now_pos movl %eax, prev_byte movl %eax, state incl %eax movl %eax, rep0 movl %eax, rep1 movl %eax, rep2 movl %eax, rep3 #ifndef FIXED_PROPS movl %eax, %edx movb pb, %cl shll %cl, %edx decl %edx movl %edx, pos_state_mask movl %eax, %edx movb lp, %cl shll %cl, %edx decl %edx movl %edx, lit_pos_mask; #endif /* RangeDecoderInit */ negl %eax movl %eax, range incl %eax movb $5, %cl 1: shll $8, %eax lodsb loop 1b movl %eax, code lzma_decode_loop: movl now_pos, %eax cmpl out_size, %eax jb 1f #ifndef ASM_FILE xorl %eax, %eax popl %ebx popl %edi popl %esi #endif movl %ebp, %esp popl %ebp ret 1: #ifdef FIXED_PROPS andl $POS_STATE_MASK, %eax #else andl pos_state_mask, %eax #endif pushl %eax /* posState */ movl state, %edx shll $kNumPosBitsMax, %edx addl %edx, %eax pushl %eax /* (state << kNumPosBitsMax) + posState */ call RangeDecoderBitDecode jc 1f movl now_pos, %eax #ifdef FIXED_PROPS andl $LIT_POS_MASK, %eax shll $FIXED_LC, %eax movl prev_byte, %edx shrl $(8 - FIXED_LC), %edx #else andl lit_pos_mask, %eax movb lc, %cl shll %cl, %eax negb %cl addb $8, %cl movl prev_byte, %edx shrl %cl, %edx #endif addl %edx, %eax movl $LZMA_LIT_SIZE, %edx mull %edx addl $Literal, %eax pushl %eax incl %edx /* edx = 1 */ movl rep0, %eax negl %eax pushl (%edi, %eax) /* matchByte */ cmpb $kNumLitStates, state jb 5f /* LzmaLiteralDecodeMatch */ 3: cmpl $0x100, %edx jae 4f xorl %eax, %eax shlb $1, (%esp) adcl %eax, %eax pushl %eax pushl %edx shll $8, %eax leal 0x100(%edx, %eax), %eax addl 12(%esp), %eax call RangeDecoderBitDecode setc %al popl %edx adcl %edx, %edx popl %ecx cmpb %cl, %al jz 3b 5: /* LzmaLiteralDecode */ cmpl $0x100, %edx jae 4f pushl %edx movl %edx, %eax addl 8(%esp), %eax call RangeDecoderBitDecode popl %edx adcl %edx, %edx jmp 5b 4: addl $16, %esp movb %dl, %al call WriteByte movb state, %al cmpb $4, %al jae 2f xorb %al, %al jmp 3f 2: subb $3, %al cmpb $7, %al jb 3f subb $3, %al 3: movb %al, state jmp lzma_decode_loop 1: movl state, %eax addl $IsRep, %eax call RangeDecoderBitDecode jnc 1f movl state, %eax addl $IsRepG0, %eax call RangeDecoderBitDecode jc 10f movl (%esp), %eax addl $IsRep0Long, %eax call RangeDecoderBitDecode jc 20f cmpb $7, state movb $9, state jb 100f addb $2, state 100: movl $1, %ecx 3: movl rep0, %edx negl %edx 4: movb (%edi, %edx), %al call WriteByte loop 4b popl %eax popl %eax jmp lzma_decode_loop 10: movl state, %eax addl $IsRepG1, %eax call RangeDecoderBitDecode movl rep1, %edx jnc 100f movl state, %eax addl $IsRepG2, %eax call RangeDecoderBitDecode movl rep2, %edx jnc 1000f movl rep2, %edx xchgl rep3, %edx 1000: pushl rep1 popl rep2 100: xchg rep0, %edx movl %edx, rep1 20: movl $RepLenCoder, %eax call LzmaLenDecode cmpb $7, state movb $8, state jb 100f addb $3, state 100: jmp 2f 1: movl rep0, %eax xchgl rep1, %eax xchgl rep2, %eax movl %eax, rep3 cmpb $7, state movb $7, state jb 10f addb $3, state 10: movl $LenCoder, %eax call LzmaLenDecode pushl %edx movl $(kNumLenToPosStates - 1), %eax cmpl %eax, %edx jbe 100f movl %eax, %edx 100: movb $kNumPosSlotBits, %cl shll %cl, %edx leal PosSlot(%edx), %eax call RangeDecoderBitTreeDecode movl %edx, rep0 cmpl $kStartPosModelIndex, %edx jb 100f movl %edx, %ecx shrl $1, %ecx decl %ecx movzbl %dl, %eax andb $1, %al orb $2, %al shll %cl, %eax movl %eax, rep0 cmpl $kEndPosModelIndex, %edx jae 200f movl rep0, %eax addl $(SpecPos - 1), %eax subl %edx, %eax jmp 300f 200: subb $kNumAlignBits, %cl /* RangeDecoderDecodeDirectBits */ xorl %edx, %edx 1000: shrl $1, range shll $1, %edx movl range, %eax cmpl %eax, code jb 2000f subl %eax, code orb $1, %dl 2000: cmpl $kTopValue, %eax jae 3000f shll $8, range shll $8, code lodsb movb %al, code 3000: loop 1000b movb $kNumAlignBits, %cl shll %cl, %edx addl %edx, rep0 movl $Align, %eax 300: call RangeDecoderReverseBitTreeDecode addl %ecx, rep0 100: incl rep0 popl %edx 2: addl $kMatchMinLen, %edx movl %edx, %ecx jmp 3b