2 * Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
4 * This file is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of
7 * the License, or (at your option) any later version.
9 * Originally this code was part of ucl the data compression library
10 * for upx the ``Ultimate Packer of eXecutables''.
12 * - Converted to gas assembly, and refitted to work with etherboot.
13 * Eric Biederman 20 Aug 2002
15 * - Structure modified to be a subroutine call rather than an
17 * Michael Brown 30 Mar 2004
19 * - Modified to be compilable as either 16-bit or 32-bit code.
20 * Michael Brown 9 Mar 2005
23 FILE_LICENCE ( GPL2_OR_LATER )
25 /****************************************************************************
26 * This file provides the decompress() and decompress16() functions
27 * which can be called in order to decompress an image compressed with
28 * the nrv2b utility in src/util.
30 * These functions are designed to be called by the prefix. They are
31 * position-independent code.
33 * The same basic assembly code is used to compile both
34 * decompress() and decompress16().
35 ****************************************************************************
40 .section ".prefix.lib", "ax", @progbits
43 /****************************************************************************
44 * decompress16 (real-mode near call, position independent)
46 * Decompress data in 16-bit mode
48 * Parameters (passed via registers):
49 * %ds:%esi - Start of compressed input data
50 * %es:%edi - Start of output buffer
52 * %ds:%esi - End of compressed input data
53 * %es:%edi - End of decompressed output data
54 * All other registers are preserved
56 * NOTE: It would be possible to build a smaller version of the
57 * decompression code for -DKEEP_IT_REAL by using
59 * to use 16-bit registers where possible. This would impose limits
60 * that the compressed data size must be in the range [1,65533-%si]
61 * and the uncompressed data size must be in the range [1,65536-%di]
62 * (where %si and %di are the input values for those registers). Note
63 * particularly that the lower limit is 1, not 0, and that the upper
64 * limit on the input (compressed) data really is 65533, since the
65 * algorithm may read up to three bytes beyond the end of the input
66 * data, since it reads dwords.
67 ****************************************************************************
79 /****************************************************************************
80 * decompress (32-bit protected-mode near call, position independent)
82 * Parameters (passed via registers):
83 * %ds:%esi - Start of compressed input data
84 * %es:%edi - Start of output buffer
86 * %ds:%esi - End of compressed input data
87 * %es:%edi - End of decompressed output data
88 * All other registers are preserved
89 ****************************************************************************
112 /* Do the decompression */
115 dec %xBP /* last_m_off = -1 */
118 decompr_literals_n2b:
126 jc decompr_literals_n2b
128 inc %xAX /* m_off = 1 */
131 adc %xAX, %xAX /* m_off = m_off*2 + getbit() */
133 jnc loop1_n2b /* while(!getbit()) */
135 jb decompr_ebpeax_n2b /* if (m_off == 2) goto decompr_ebpeax_n2b ? */
137 ADDR32 movb (%xSI), %al /* m_off = (m_off - 3)*256 + src[ilen++] */
140 jz decompr_end_n2b /* if (m_off == 0xffffffff) goto decomp_end_n2b */
141 mov %xAX, %xBP /* last_m_off = m_off ?*/
145 adc %xCX, %xCX /* m_len = getbit() */
147 adc %xCX, %xCX /* m_len = m_len*2 + getbit()) */
148 jnz decompr_got_mlen_n2b /* if (m_len == 0) goto decompr_got_mlen_n2b */
149 inc %xCX /* m_len++ */
152 adc %xCX, %xCX /* m_len = m_len*2 + getbit() */
154 jnc loop2_n2b /* while(!getbit()) */
156 inc %xCX /* m_len += 2 */
157 decompr_got_mlen_n2b:
159 adc $1, %xCX /* m_len = m_len + 1 + (last_m_off > 0xd00) */
161 ADDR32 lea (%xBP,%xDI), %xSI /* m_pos = dst + olen + -m_off */
163 es ADDR32 movsb /* dst[olen++] = *m_pos++ while(m_len > 0) */
172 ADDR32 movl (%xSI), %ebx
173 sub $-4, %xSI /* sets carry flag */
179 /* Restore registers and return */