You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

unnrv2b.S 5.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. /*
  2. * Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
  3. *
  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.
  8. *
  9. * Originally this code was part of ucl the data compression library
  10. * for upx the ``Ultimate Packer of eXecutables''.
  11. *
  12. * - Converted to gas assembly, and refitted to work with etherboot.
  13. * Eric Biederman 20 Aug 2002
  14. *
  15. * - Structure modified to be a subroutine call rather than an
  16. * executable prefix.
  17. * Michael Brown 30 Mar 2004
  18. *
  19. * - Modified to be compilable as either 16-bit or 32-bit code.
  20. * Michael Brown 9 Mar 2005
  21. */
  22. FILE_LICENCE ( GPL2_OR_LATER )
  23. /****************************************************************************
  24. * This file provides the decompress() and decompress16() functions
  25. * which can be called in order to decompress an image compressed with
  26. * the nrv2b utility in src/util.
  27. *
  28. * These functions are designed to be called by the prefix. They are
  29. * position-independent code.
  30. *
  31. * The same basic assembly code is used to compile both
  32. * decompress() and decompress16().
  33. ****************************************************************************
  34. */
  35. .text
  36. .arch i386
  37. .section ".prefix.lib", "ax", @progbits
  38. #ifdef CODE16
  39. /****************************************************************************
  40. * decompress16 (real-mode near call, position independent)
  41. *
  42. * Decompress data in 16-bit mode
  43. *
  44. * Parameters (passed via registers):
  45. * %ds:%esi - Start of compressed input data
  46. * %es:%edi - Start of output buffer
  47. * Returns:
  48. * %ds:%esi - End of compressed input data
  49. * %es:%edi - End of decompressed output data
  50. * All other registers are preserved
  51. *
  52. * NOTE: It would be possible to build a smaller version of the
  53. * decompression code for -DKEEP_IT_REAL by using
  54. * #define REG(x) x
  55. * to use 16-bit registers where possible. This would impose limits
  56. * that the compressed data size must be in the range [1,65533-%si]
  57. * and the uncompressed data size must be in the range [1,65536-%di]
  58. * (where %si and %di are the input values for those registers). Note
  59. * particularly that the lower limit is 1, not 0, and that the upper
  60. * limit on the input (compressed) data really is 65533, since the
  61. * algorithm may read up to three bytes beyond the end of the input
  62. * data, since it reads dwords.
  63. ****************************************************************************
  64. */
  65. #define REG(x) e ## x
  66. #define ADDR32 addr32
  67. .code16
  68. .globl decompress16
  69. decompress16:
  70. #else /* CODE16 */
  71. /****************************************************************************
  72. * decompress (32-bit protected-mode near call, position independent)
  73. *
  74. * Parameters (passed via registers):
  75. * %ds:%esi - Start of compressed input data
  76. * %es:%edi - Start of output buffer
  77. * Returns:
  78. * %ds:%esi - End of compressed input data
  79. * %es:%edi - End of decompressed output data
  80. * All other registers are preserved
  81. ****************************************************************************
  82. */
  83. #define REG(x) e ## x
  84. #define ADDR32
  85. .code32
  86. .globl decompress
  87. decompress:
  88. #endif /* CODE16 */
  89. #define xAX REG(ax)
  90. #define xCX REG(cx)
  91. #define xBP REG(bp)
  92. #define xSI REG(si)
  93. #define xDI REG(di)
  94. /* Save registers */
  95. push %xAX
  96. pushl %ebx
  97. push %xCX
  98. push %xBP
  99. /* Do the decompression */
  100. cld
  101. xor %xBP, %xBP
  102. dec %xBP /* last_m_off = -1 */
  103. jmp dcl1_n2b
  104. decompr_literals_n2b:
  105. ADDR32 movsb
  106. decompr_loop_n2b:
  107. addl %ebx, %ebx
  108. jnz dcl2_n2b
  109. dcl1_n2b:
  110. call getbit32
  111. dcl2_n2b:
  112. jc decompr_literals_n2b
  113. xor %xAX, %xAX
  114. inc %xAX /* m_off = 1 */
  115. loop1_n2b:
  116. call getbit1
  117. adc %xAX, %xAX /* m_off = m_off*2 + getbit() */
  118. call getbit1
  119. jnc loop1_n2b /* while(!getbit()) */
  120. sub $3, %xAX
  121. jb decompr_ebpeax_n2b /* if (m_off == 2) goto decompr_ebpeax_n2b ? */
  122. shl $8, %xAX
  123. ADDR32 movb (%xSI), %al /* m_off = (m_off - 3)*256 + src[ilen++] */
  124. inc %xSI
  125. xor $-1, %xAX
  126. jz decompr_end_n2b /* if (m_off == 0xffffffff) goto decomp_end_n2b */
  127. mov %xAX, %xBP /* last_m_off = m_off ?*/
  128. decompr_ebpeax_n2b:
  129. xor %xCX, %xCX
  130. call getbit1
  131. adc %xCX, %xCX /* m_len = getbit() */
  132. call getbit1
  133. adc %xCX, %xCX /* m_len = m_len*2 + getbit()) */
  134. jnz decompr_got_mlen_n2b /* if (m_len == 0) goto decompr_got_mlen_n2b */
  135. inc %xCX /* m_len++ */
  136. loop2_n2b:
  137. call getbit1
  138. adc %xCX, %xCX /* m_len = m_len*2 + getbit() */
  139. call getbit1
  140. jnc loop2_n2b /* while(!getbit()) */
  141. inc %xCX
  142. inc %xCX /* m_len += 2 */
  143. decompr_got_mlen_n2b:
  144. cmp $-0xd00, %xBP
  145. adc $1, %xCX /* m_len = m_len + 1 + (last_m_off > 0xd00) */
  146. push %xSI
  147. ADDR32 lea (%xBP,%xDI), %xSI /* m_pos = dst + olen + -m_off */
  148. rep
  149. es ADDR32 movsb /* dst[olen++] = *m_pos++ while(m_len > 0) */
  150. pop %xSI
  151. jmp decompr_loop_n2b
  152. getbit1:
  153. addl %ebx, %ebx
  154. jnz 1f
  155. getbit32:
  156. ADDR32 movl (%xSI), %ebx
  157. sub $-4, %xSI /* sets carry flag */
  158. adcl %ebx, %ebx
  159. 1:
  160. ret
  161. decompr_end_n2b:
  162. /* Restore registers and return */
  163. pop %xBP
  164. pop %xCX
  165. popl %ebx
  166. pop %xAX
  167. ret