123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182 |
- /*
- * Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
- *
- * This file 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 2 of
- * the License, or (at your option) any later version.
- *
- * Originally this code was part of ucl the data compression library
- * for upx the ``Ultimate Packer of eXecutables''.
- *
- * - Converted to gas assembly, and refitted to work with etherboot.
- * Eric Biederman 20 Aug 2002
- *
- * - Structure modified to be a subroutine call rather than an
- * executable prefix.
- * Michael Brown 30 Mar 2004
- *
- * - Modified to be compilable as either 16-bit or 32-bit code.
- * Michael Brown 9 Mar 2005
- */
-
- /****************************************************************************
- * This file provides the decompress() and decompress16() functions
- * which can be called in order to decompress an image compressed with
- * the nrv2b utility in src/util.
- *
- * These functions are designed to be called by the prefix. They are
- * position-independent code.
- *
- * The same basic assembly code is used to compile both
- * decompress() and decompress16().
- ****************************************************************************
- */
-
- .text
- .arch i386
- .section ".prefix.lib", "ax", @progbits
-
- #ifdef CODE16
- /****************************************************************************
- * decompress16 (real-mode near call, position independent)
- *
- * Decompress data in 16-bit mode
- *
- * Parameters (passed via registers):
- * %ds:%esi - Start of compressed input data
- * %es:%edi - Start of output buffer
- * Returns:
- * %ds:%esi - End of compressed input data
- * %es:%edi - End of decompressed output data
- * All other registers are preserved
- *
- * NOTE: It would be possible to build a smaller version of the
- * decompression code for -DKEEP_IT_REAL by using
- * #define REG(x) x
- * to use 16-bit registers where possible. This would impose limits
- * that the compressed data size must be in the range [1,65533-%si]
- * and the uncompressed data size must be in the range [1,65536-%di]
- * (where %si and %di are the input values for those registers). Note
- * particularly that the lower limit is 1, not 0, and that the upper
- * limit on the input (compressed) data really is 65533, since the
- * algorithm may read up to three bytes beyond the end of the input
- * data, since it reads dwords.
- ****************************************************************************
- */
-
- #define REG(x) e ## x
- #define ADDR32 addr32
-
- .code16
- .globl decompress16
- decompress16:
-
- #else /* CODE16 */
-
- /****************************************************************************
- * decompress (32-bit protected-mode near call, position independent)
- *
- * Parameters (passed via registers):
- * %ds:%esi - Start of compressed input data
- * %es:%edi - Start of output buffer
- * Returns:
- * %ds:%esi - End of compressed input data
- * %es:%edi - End of decompressed output data
- * All other registers are preserved
- ****************************************************************************
- */
-
- #define REG(x) e ## x
- #define ADDR32
-
- .code32
- .globl decompress
- decompress:
-
- #endif /* CODE16 */
-
- #define xAX REG(ax)
- #define xCX REG(cx)
- #define xBP REG(bp)
- #define xSI REG(si)
- #define xDI REG(di)
-
- /* Save registers */
- push %xAX
- pushl %ebx
- push %xCX
- push %xBP
- /* Do the decompression */
- cld
- xor %xBP, %xBP
- dec %xBP /* last_m_off = -1 */
- jmp dcl1_n2b
-
- decompr_literals_n2b:
- ADDR32 movsb
- decompr_loop_n2b:
- addl %ebx, %ebx
- jnz dcl2_n2b
- dcl1_n2b:
- call getbit32
- dcl2_n2b:
- jc decompr_literals_n2b
- xor %xAX, %xAX
- inc %xAX /* m_off = 1 */
- loop1_n2b:
- call getbit1
- adc %xAX, %xAX /* m_off = m_off*2 + getbit() */
- call getbit1
- jnc loop1_n2b /* while(!getbit()) */
- sub $3, %xAX
- jb decompr_ebpeax_n2b /* if (m_off == 2) goto decompr_ebpeax_n2b ? */
- shl $8, %xAX
- ADDR32 movb (%xSI), %al /* m_off = (m_off - 3)*256 + src[ilen++] */
- inc %xSI
- xor $-1, %xAX
- jz decompr_end_n2b /* if (m_off == 0xffffffff) goto decomp_end_n2b */
- mov %xAX, %xBP /* last_m_off = m_off ?*/
- decompr_ebpeax_n2b:
- xor %xCX, %xCX
- call getbit1
- adc %xCX, %xCX /* m_len = getbit() */
- call getbit1
- adc %xCX, %xCX /* m_len = m_len*2 + getbit()) */
- jnz decompr_got_mlen_n2b /* if (m_len == 0) goto decompr_got_mlen_n2b */
- inc %xCX /* m_len++ */
- loop2_n2b:
- call getbit1
- adc %xCX, %xCX /* m_len = m_len*2 + getbit() */
- call getbit1
- jnc loop2_n2b /* while(!getbit()) */
- inc %xCX
- inc %xCX /* m_len += 2 */
- decompr_got_mlen_n2b:
- cmp $-0xd00, %xBP
- adc $1, %xCX /* m_len = m_len + 1 + (last_m_off > 0xd00) */
- push %xSI
- ADDR32 lea (%xBP,%xDI), %xSI /* m_pos = dst + olen + -m_off */
- rep
- es ADDR32 movsb /* dst[olen++] = *m_pos++ while(m_len > 0) */
- pop %xSI
- jmp decompr_loop_n2b
-
-
- getbit1:
- addl %ebx, %ebx
- jnz 1f
- getbit32:
- ADDR32 movl (%xSI), %ebx
- sub $-4, %xSI /* sets carry flag */
- adcl %ebx, %ebx
- 1:
- ret
-
- decompr_end_n2b:
- /* Restore registers and return */
- pop %xBP
- pop %xCX
- popl %ebx
- pop %xAX
- ret
|