summaryrefslogtreecommitdiffstats
path: root/grub-core/boot/i386/pc/lzma_decode.S
diff options
context:
space:
mode:
Diffstat (limited to 'grub-core/boot/i386/pc/lzma_decode.S')
-rw-r--r--grub-core/boot/i386/pc/lzma_decode.S614
1 files changed, 614 insertions, 0 deletions
diff --git a/grub-core/boot/i386/pc/lzma_decode.S b/grub-core/boot/i386/pc/lzma_decode.S
new file mode 100644
index 0000000..88c668d
--- /dev/null
+++ b/grub-core/boot/i386/pc/lzma_decode.S
@@ -0,0 +1,614 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#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