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.

unlzma.S 23KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939
  1. /*
  2. * Copyright (C) 2015 Michael Brown <mbrown@fensystems.co.uk>.
  3. *
  4. * This program 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 the
  7. * License, or (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful, but
  10. * WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  17. * 02110-1301, USA.
  18. *
  19. * You can also choose to distribute this program under the terms of
  20. * the Unmodified Binary Distribution Licence (as given in the file
  21. * COPYING.UBDL), provided that you have satisfied its requirements.
  22. */
  23. FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
  24. /****************************************************************************
  25. *
  26. * This file provides the decompress() and decompress16() functions
  27. * which can be called in order to decompress an LZMA-compressed
  28. * image. The code is modelled on the public-domain "XZ Embedded"
  29. * implementation as used by the Linux kernel. Symbol names are
  30. * chosen to match the XZ Embedded implementation where possible, for
  31. * ease of reference.
  32. *
  33. * This code is optimised for size rather than speed, since the amount
  34. * of data to be decompressed is trivially small by modern standards.
  35. *
  36. * The same basic assembly code is used to compile both decompress()
  37. * and decompress16().
  38. *
  39. * Note that these functions require large amounts of stack space.
  40. *
  41. ****************************************************************************
  42. */
  43. .text
  44. .arch i586
  45. .section ".prefix.lib", "ax", @progbits
  46. #ifdef CODE16
  47. #define ADDR16
  48. #define ADDR32 addr32
  49. #define decompress decompress16
  50. .code16
  51. #else /* CODE16 */
  52. #define ADDR16 addr16
  53. #define ADDR32
  54. .code32
  55. #endif /* CODE16 */
  56. /****************************************************************************
  57. * Debugging
  58. ****************************************************************************
  59. *
  60. * This code will usually run in 16-bit protected mode, in which case
  61. * only the 0xe9 debug port (present on some virtual machines) can be
  62. * used.
  63. *
  64. * To debug on real hardware, build with DEBUG=libprefix. This will
  65. * cause this code to be called in flat real mode, and so DEBUG_INT10
  66. * may be used.
  67. */
  68. /* Enable debugging via 0xe9 debug port */
  69. #define DEBUG_E9 0
  70. /* Enable debugging via BIOS INT 10 (works only when in flat real mode) */
  71. #define DEBUG_INT10 0
  72. #if ( DEBUG_E9 || DEBUG_INT10 )
  73. .macro print_character, reg
  74. pushfl
  75. pushw %ax
  76. pushw %bx
  77. pushw %bp
  78. movb \reg, %al
  79. movw $0x0007, %bx
  80. movb $0x0e, %ah
  81. #if DEBUG_E9
  82. outb %al, $0xe9
  83. #endif
  84. #if DEBUG_INT10
  85. cmpb $('\n'), %al
  86. jne L\@
  87. int $0x10
  88. movb $('\r'), %al
  89. L\@: int $0x10
  90. #endif
  91. popw %bp
  92. popw %bx
  93. popw %ax
  94. popfl
  95. .endm
  96. .macro print_hex_nibble
  97. pushfl
  98. pushw %ax
  99. cmpb $10, %al
  100. sbb $0x69, %al
  101. das
  102. print_character %al
  103. popw %ax
  104. popfl
  105. .endm
  106. .macro print_hex_byte, reg
  107. pushfl
  108. pushw %ax
  109. movb \reg, %al
  110. pushw %ax
  111. shrb $4, %al
  112. print_hex_nibble
  113. popw %ax
  114. andb $0x0f, %al
  115. print_hex_nibble
  116. popw %ax
  117. popfl
  118. .endm
  119. .macro print_hex_word, reg
  120. pushw %ax
  121. movw \reg, %ax
  122. print_hex_byte %ah
  123. print_hex_byte %al
  124. popw %ax
  125. .endm
  126. .macro print_hex_dword, reg
  127. pushl %eax
  128. movl \reg, %eax
  129. rorl $16, %eax
  130. print_hex_word %ax
  131. rorl $16, %eax
  132. print_hex_word %ax
  133. popl %eax
  134. .endm
  135. #else
  136. .macro print_character, char
  137. .endm
  138. .macro print_hex_byte, reg
  139. .endm
  140. .macro print_hex_word, reg
  141. .endm
  142. .macro print_hex_dword, reg
  143. .endm
  144. #endif
  145. /****************************************************************************
  146. * LZMA parameters and data structures
  147. ****************************************************************************
  148. */
  149. /* LZMA decompressor states (as used in XZ Embedded) */
  150. #define STATE_LIT_LIT 0x00
  151. #define STATE_MATCH_LIT_LIT 0x01
  152. #define STATE_REP_LIT_LIT 0x02
  153. #define STATE_SHORTREP_LIT_LIT 0x03
  154. #define STATE_MATCH_LIT 0x04
  155. #define STATE_REP_LIT 0x05
  156. #define STATE_SHORTREP_LIT 0x06
  157. #define STATE_LIT_MATCH 0x07
  158. #define STATE_LIT_LONGREP 0x08
  159. #define STATE_LIT_SHORTREP 0x09
  160. #define STATE_NONLIT_MATCH 0x0a
  161. #define STATE_NONLIT_REP 0x0b
  162. /* LZMA maximum decompressor state in which most recent symbol was a literal */
  163. #define STATE_LIT_MAX 0x06
  164. /* LZMA number of literal context bits ("lc=" parameter) */
  165. #define LZMA_LC 2
  166. .struct 0
  167. lzma_len_dec:
  168. choice: .word 0
  169. choice2: .word 0
  170. low: .rept ( 1 << 3 )
  171. .word 0
  172. .endr
  173. mid: .rept ( 1 << 3 )
  174. .word 0
  175. .endr
  176. high: .rept ( 1 << 8 )
  177. .word 0
  178. .endr
  179. .equ sizeof__lzma_len_dec, . - lzma_len_dec
  180. .previous
  181. .struct 0
  182. lzma_dec:
  183. out_start: .long 0
  184. rc_code: .long 0
  185. rc_range: .long 0
  186. len: .word 0
  187. reps:
  188. rep0: .long 0
  189. rep1: .long 0
  190. rep2: .long 0
  191. rep3: .long 0
  192. probs:
  193. is_match: .word 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  194. is_rep: .word 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  195. is_rep0: .word 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  196. is_rep1: .word 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  197. is_rep2: .word 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  198. is_rep0_long: .word 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  199. dist_slot: .rept ( 4 * ( 1 << 6 ) )
  200. .word 0
  201. .endr
  202. dist_special: .rept ( ( 1 << ( 14 / 2 ) ) - 14 )
  203. .word 0
  204. .endr
  205. dist_align: .rept ( 1 << 4 )
  206. .word 0
  207. .endr
  208. match_len_dec: .space sizeof__lzma_len_dec
  209. rep_len_dec: .space sizeof__lzma_len_dec
  210. literal: .rept ( ( 1 << LZMA_LC ) * 0x300 )
  211. .word 0
  212. .endr
  213. .align 4
  214. .equ sizeof__lzma_dec, . - lzma_dec
  215. .previous
  216. /*****************************************************************************
  217. * Normalise range encoder
  218. *
  219. * Parameters:
  220. * %ss:%ebp : LZMA parameter block
  221. * %ds:%esi : compressed input data pointer
  222. * Returns:
  223. * %ds:%esi : compressed input data pointer (possibly updated)
  224. * %eax : current range
  225. *****************************************************************************
  226. */
  227. rc_normalise:
  228. /* Check if rc_range is less than 1<<24 */
  229. testb $0xff, (rc_range+3)(%ebp)
  230. jnz 1f
  231. /* If it is, shift in a new byte from the compressed input data */
  232. shll $8, rc_range(%ebp)
  233. shll $8, rc_code(%ebp)
  234. ADDR32 lodsb
  235. movb %al, (rc_code+0)(%ebp)
  236. 1: /* Return current range */
  237. movl rc_range(%ebp), %eax
  238. ret
  239. .size rc_normalise, . - rc_normalise
  240. /*****************************************************************************
  241. * Decode single range-encoded bit using a probability estimate
  242. *
  243. * Parameters:
  244. * %ss:%ebp : LZMA parameter block
  245. * %ds:%esi : compressed input data pointer
  246. * %ebx : probability estimate pointer (offset from %ebp)
  247. * Returns:
  248. * %ds:%esi : compressed input data pointer (possibly updated)
  249. * CF : decoded bit
  250. * ZF : inverse of decoded bit
  251. * Corrupts:
  252. * none
  253. *****************************************************************************
  254. */
  255. rc_bit:
  256. /* Preserve registers */
  257. pushl %eax
  258. pushl %edx
  259. /* Perform normalisation */
  260. call rc_normalise
  261. /* Calculate bound in %eax and probability estimate in %dx */
  262. shrl $11, %eax
  263. movzwl (%ebp,%ebx), %edx
  264. mul %edx /* will zero %edx */
  265. movw (%ebp,%ebx), %dx
  266. /* Compare code against bound */
  267. cmpl %eax, rc_code(%ebp)
  268. jae 2f
  269. 1: /* Code is less than bound */
  270. movl %eax, rc_range(%ebp)
  271. negw %dx
  272. addw $(1<<11), %dx
  273. shrw $5, %dx
  274. addw %dx, (%ebp,%ebx)
  275. xorw %ax, %ax /* Clear CF, set ZF */
  276. jmp 99f
  277. 2: /* Code is greater than or equal to bound */
  278. subl %eax, rc_range(%ebp)
  279. subl %eax, rc_code(%ebp)
  280. shrw $5, %dx
  281. subw %dx, (%ebp,%ebx)
  282. incw %dx /* Clear ZF (%dx is 11-bit; can never wrap) */
  283. stc /* Set CF */
  284. 99: /* Restore registers and return */
  285. popl %edx
  286. popl %eax
  287. ret
  288. .size rc_bit, . - rc_bit
  289. /*****************************************************************************
  290. * Decode MSB-first bittree
  291. *
  292. * Parameters:
  293. * %ss:%ebp : LZMA parameter block
  294. * %ds:%esi : compressed input data pointer
  295. * %ebx : probability estimate set pointer (offset from %ebp)
  296. * %cx : number of bits to decode
  297. * Returns:
  298. * %ds:%esi : compressed input data pointer (possibly updated)
  299. * %eax : decoded bittree
  300. * Corrupts:
  301. * none
  302. *****************************************************************************
  303. */
  304. rc_bittree:
  305. /* Preserve registers */
  306. pushl %edi
  307. pushw %cx
  308. movl %ebx, %edi
  309. /* Initialise registers */
  310. movl $1, %eax
  311. 1: /* Decode bit */
  312. leaw (%edi,%eax,2), %bx /* high word always zero anyway */
  313. call rc_bit
  314. rclw %ax
  315. ADDR16 loop 1b
  316. /* Restore registers, clear unwanted high bit of result, and return */
  317. movl %edi, %ebx
  318. popw %cx
  319. popl %edi
  320. btrw %cx, %ax
  321. ret
  322. .size rc_bittree, . - rc_bittree
  323. /*****************************************************************************
  324. * Decode LSB-first bittree
  325. *
  326. * Parameters:
  327. * %ss:%ebp : LZMA parameter block
  328. * %ds:%esi : compressed input data pointer
  329. * %ebx : probability estimate set pointer (offset from %ebp)
  330. * %cx : number of bits to decode
  331. * Returns:
  332. * %ds:%esi : compressed input data pointer (possibly updated)
  333. * %eax : decoded bittree
  334. * Corrupts:
  335. * none
  336. *****************************************************************************
  337. */
  338. rc_bittree_reverse:
  339. /* Preserve registers */
  340. pushw %cx
  341. /* Decode bittree */
  342. call rc_bittree
  343. 1: /* Reverse result */
  344. rcrb %al
  345. rclb %ah
  346. ADDR16 loop 1b
  347. shrw $8, %ax
  348. /* Restore registers and return */
  349. popw %cx
  350. ret
  351. .size rc_bittree_reverse, . - rc_bittree_reverse
  352. /*****************************************************************************
  353. * Decode MSB-first bittree with optional match byte
  354. *
  355. * Parameters:
  356. * %ss:%ebp : LZMA parameter block
  357. * %ds:%esi : compressed input data pointer
  358. * %ebx : probability estimate set pointer (offset from %ebp)
  359. * %cl : match byte
  360. * %ch : 1 to use match byte, 0 to ignore match byte
  361. * Returns:
  362. * %ds:%esi : compressed input data pointer (possibly updated)
  363. * %eax : decoded bittree
  364. * Corrupts:
  365. * none
  366. *****************************************************************************
  367. */
  368. rc_bittree_match:
  369. /* Preserve registers */
  370. pushl %edi
  371. pushw %cx
  372. pushw %dx
  373. movl %ebx, %edi
  374. /* Initialise registers */
  375. movl $1, %eax
  376. 1: /* Decode bit */
  377. rolb $1, %cl
  378. movw %cx, %dx
  379. andb %dh, %dl /* match_bit in %dl */
  380. movw %dx, %bx
  381. addb %bl, %bh
  382. xorb %bl, %bl
  383. addw %ax, %bx /* offset + match_bit + symbol */
  384. leaw (%edi,%ebx,2), %bx /* high word always zero anyway */
  385. call rc_bit
  386. rclw %ax
  387. movb %al, %dh
  388. notb %dh
  389. xorb %dh, %dl
  390. andb %dl, %ch /* offset &= ( match_bit ^ bit ) */
  391. testb %ah, %ah
  392. jz 1b
  393. /* Restore registers, clear unwanted high bit of result, and return */
  394. movl %edi, %ebx
  395. popw %dx
  396. popw %cx
  397. popl %edi
  398. xorb %ah, %ah
  399. ret
  400. .size rc_bittree_match, . - rc_bittree_match
  401. /*****************************************************************************
  402. * Decode direct bits (no probability estimates)
  403. *
  404. * Parameters:
  405. * %ss:%ebp : LZMA parameter block
  406. * %ds:%esi : compressed input data pointer
  407. * %cx : number of bits to decode
  408. * Returns:
  409. * %ds:%esi : compressed input data pointer (possibly updated)
  410. * %eax : decoded bits
  411. * Corrupts:
  412. * none
  413. *****************************************************************************
  414. */
  415. rc_direct:
  416. /* Preserve registers */
  417. pushl %ebx
  418. pushw %cx
  419. pushl %edx
  420. /* Initialise registers */
  421. xorl %edx, %edx
  422. 1: /* Perform normalisation */
  423. call rc_normalise
  424. /* Decode bit */
  425. shrl $1, %eax
  426. movl %eax, rc_range(%ebp)
  427. movl rc_code(%ebp), %ebx
  428. subl %eax, %ebx
  429. js 2f
  430. movl %ebx, rc_code(%ebp)
  431. 2: rcll %ebx
  432. rcll %edx
  433. xorb $1, %dl
  434. ADDR16 loop 1b
  435. /* Restore registers and return */
  436. movl %edx, %eax
  437. popl %edx
  438. popw %cx
  439. popl %ebx
  440. ret
  441. .size rc_direct, . - rc_direct
  442. /*****************************************************************************
  443. * Decode an LZMA literal
  444. *
  445. * Parameters:
  446. * %ss:%ebp : LZMA parameter block
  447. * %ds:%esi : compressed input data pointer
  448. * %es:%edi : uncompressed output data pointer
  449. * %edx : LZMA state
  450. * Returns:
  451. * %ds:%esi : compressed input data pointer (possibly updated)
  452. * %es:%edi : uncompressed output data pointer (updated)
  453. * %edx : LZMA state
  454. * CF : end of payload marker found (always zero)
  455. * Corrupts:
  456. * %eax
  457. * %ebx
  458. * %ecx
  459. *****************************************************************************
  460. *
  461. * Literals are coded as an eight-bit tree, using a match byte if the
  462. * previous symbol was not a literal.
  463. *
  464. */
  465. lzma_literal:
  466. /* Get most recent output byte, if available */
  467. xorl %ebx, %ebx
  468. cmpl %edi, out_start(%ebp)
  469. je 1f
  470. movb %es:-1(%edi), %bh
  471. 1: /* Locate probability estimate set */
  472. shrb $( 8 - LZMA_LC ), %bh
  473. shlb $1, %bh
  474. leaw literal(%ebx,%ebx,2), %bx
  475. /* Get match byte, if applicable */
  476. xorw %cx, %cx
  477. cmpb $STATE_LIT_MAX, %dl
  478. jbe 1f
  479. movl rep0(%ebp), %eax
  480. notl %eax
  481. movb %es:(%edi,%eax), %cl
  482. movb $1, %ch
  483. 1: /* Decode bittree */
  484. call rc_bittree_match
  485. /* Store output byte */
  486. ADDR32 stosb
  487. print_hex_byte %al
  488. print_character $(' ')
  489. /* Update LZMA state */
  490. subb $3, %dl
  491. jns 1f
  492. xorb %dl, %dl
  493. 1: cmpb $7, %dl
  494. jb 1f
  495. subb $3, %dl
  496. 1: /* Clear CF and return */
  497. clc
  498. ret
  499. .size lzma_literal, . - lzma_literal
  500. /*****************************************************************************
  501. * Decode an LZMA length
  502. *
  503. * Parameters:
  504. * %ss:%ebp : LZMA parameter block
  505. * %ds:%esi : compressed input data pointer
  506. * %ebx : length parameter pointer (offset from %ebp)
  507. * Returns:
  508. * %ds:%esi : compressed input data pointer (possibly updated)
  509. * Corrupts:
  510. * %ebx
  511. *****************************************************************************
  512. *
  513. * Lengths are encoded as:
  514. *
  515. * "0" + 3 bits : lengths 2-9 ("low")
  516. * "10" + 3 bits : lengths 10-17 ("mid")
  517. * "11" + 8 bits : lengths 18-273 ("high")
  518. */
  519. lzma_len:
  520. /* Preserve registers */
  521. pushl %eax
  522. pushl %ecx
  523. pushl %edi
  524. movl %ebx, %edi
  525. /* Start by assuming three bits and a base length of 2 */
  526. movw $3, %cx
  527. movw $2, len(%ebp)
  528. /* Check low-length choice bit */
  529. leal choice(%edi), %ebx
  530. call rc_bit
  531. leal low(%edi), %ebx
  532. jz 1f
  533. /* Check high-length choice bit */
  534. leal choice2(%edi), %ebx
  535. call rc_bit
  536. leal mid(%edi), %ebx
  537. movb $10, len(%ebp)
  538. jz 1f
  539. leal high(%edi), %ebx
  540. movb $8, %cl
  541. movb $18, len(%ebp)
  542. 1: /* Get encoded length */
  543. call rc_bittree
  544. addw %ax, len(%ebp)
  545. /* Restore registers and return */
  546. movl %edi, %ebx
  547. popl %edi
  548. popl %ecx
  549. popl %eax
  550. ret
  551. .size lzma_len, . - lzma_len
  552. /*****************************************************************************
  553. * Copy (possibly repeated) matched data
  554. *
  555. * Parameters:
  556. * %ss:%ebp : LZMA parameter block
  557. * %ds:%esi : compressed input data pointer
  558. * %es:%edi : uncompressed output data pointer
  559. * %cl : repeated match distance index (for repeated matches)
  560. * %eax : match distance (for non-repeated matches)
  561. * Returns:
  562. * %ds:%esi : compressed input data pointer (possibly updated)
  563. * %es:%edi : uncompressed output data pointer
  564. * CF : match distance is out of range
  565. * Corrupts:
  566. * %eax
  567. * %ebx
  568. * %ecx
  569. *****************************************************************************
  570. */
  571. match: /* Update repeated match list */
  572. print_character $('[')
  573. movl $3, %ecx
  574. jmp 1f
  575. match_rep:
  576. print_character $('[')
  577. print_character $('R')
  578. print_hex_byte %cl
  579. print_character $('=')
  580. movzbl %cl, %ecx
  581. movl reps(%ebp,%ecx,4), %eax
  582. jcxz 2f
  583. 1: movl (reps-4)(%ebp,%ecx,4), %ebx
  584. movl %ebx, reps(%ebp,%ecx,4)
  585. loop 1b
  586. movl %eax, rep0(%ebp)
  587. 2: /* Preserve registers */
  588. pushl %esi
  589. /* Get stored match length */
  590. movzwl len(%ebp), %ecx
  591. print_hex_dword %eax
  592. print_character $('+')
  593. print_hex_word %cx
  594. print_character $(']')
  595. print_character $(' ')
  596. /* Abort with CF set if match distance is out of range */
  597. movl out_start(%ebp), %esi
  598. negl %esi
  599. leal -1(%edi,%esi), %esi
  600. cmpl %eax, %esi
  601. jc 99f
  602. /* Perform copy */
  603. notl %eax
  604. leal (%edi,%eax), %esi
  605. ADDR32 es rep movsb
  606. 99: /* Restore registers and return */
  607. popl %esi
  608. ret
  609. .size match, . - match
  610. /*****************************************************************************
  611. * Decode an LZMA match
  612. *
  613. * Parameters:
  614. * %ss:%ebp : LZMA parameter block
  615. * %ds:%esi : compressed input data pointer
  616. * %es:%edi : uncompressed output data pointer
  617. * %edx : LZMA state
  618. * Returns:
  619. * %ds:%esi : compressed input data pointer (possibly updated)
  620. * %es:%edi : uncompressed output data pointer
  621. * %edx : LZMA state
  622. * CF : end of payload marker found
  623. * Corrupts:
  624. * %eax
  625. * %ebx
  626. * %ecx
  627. *****************************************************************************
  628. *
  629. * Matches are encoded as an LZMA length followed by a 6-bit "distance
  630. * slot" code, 0-26 fixed-probability bits, and 0-5 context encoded
  631. * bits.
  632. */
  633. lzma_match:
  634. /* Preserve registers */
  635. pushl %edi
  636. /* Update LZMA state */
  637. cmpb $STATE_LIT_MAX, %dl
  638. movb $STATE_LIT_MATCH, %dl
  639. jbe 1f
  640. movb $STATE_NONLIT_MATCH, %dl
  641. 1: /* Decode length */
  642. movl $match_len_dec, %ebx
  643. call lzma_len
  644. /* Decode distance slot */
  645. movw len(%ebp), %bx
  646. subw $2, %bx
  647. cmpw $4, %bx
  648. jb 1f
  649. movw $3, %bx
  650. 1: shlw $7, %bx
  651. addw $dist_slot, %bx
  652. movw $6, %cx
  653. call rc_bittree
  654. /* Distance slots 0-3 are literal distances */
  655. cmpb $4, %al
  656. jb 99f
  657. /* Determine initial bits: 10/11 for even/odd distance codes */
  658. movl %eax, %edi
  659. andw $1, %di
  660. orw $2, %di
  661. /* Determine number of context-encoded bits */
  662. movw %ax, %cx
  663. shrb $1, %cl
  664. decb %cl
  665. /* Select context to be used in absence of fixed-probability bits */
  666. movl %edi, %ebx
  667. shlw %cl, %bx
  668. subw %ax, %bx
  669. leaw (dist_special-2)(%ebx,%ebx), %bx
  670. /* Decode fixed-probability bits, if any */
  671. cmpb $6, %cl
  672. jb 1f
  673. subb $4, %cl
  674. shll %cl, %edi
  675. call rc_direct
  676. orl %eax, %edi
  677. /* Select context to be used in presence of fixed-probability bits */
  678. movb $4, %cl
  679. movl $dist_align, %ebx
  680. 1: /* Decode context-encoded bits */
  681. shll %cl, %edi
  682. call rc_bittree_reverse
  683. orl %edi, %eax
  684. 99: /* Restore registers and tail-call */
  685. popl %edi
  686. jmp match
  687. .size lzma_match, . - lzma_match
  688. /*****************************************************************************
  689. * Decode an LZMA repeated match
  690. *
  691. * Parameters:
  692. * %ss:%ebp : LZMA parameter block
  693. * %ds:%esi : compressed input data pointer
  694. * %es:%edi : uncompressed output data pointer
  695. * %edx : LZMA state
  696. * Returns:
  697. * %ds:%esi : compressed input data pointer (possibly updated)
  698. * %es:%edi : uncompressed output data pointer
  699. * %edx : LZMA state
  700. * CF : end of payload marker found
  701. * Corrupts:
  702. * %eax
  703. * %ebx
  704. * %ecx
  705. *****************************************************************************
  706. *
  707. * Repeated matches are encoded as:
  708. *
  709. * "00" : shortrep0 (implicit length 1)
  710. * "01" + len : longrep0
  711. * "10" + len : longrep1
  712. * "110" + len : longrep2
  713. * "111" + len : longrep3
  714. */
  715. lzma_rep_match:
  716. /* Initially assume longrep0 */
  717. movw $(STATE_LIT_LONGREP << 8), %cx
  718. /* Get is_rep0 bit */
  719. leal is_rep0(,%edx,2), %ebx
  720. call rc_bit
  721. jnz 1f
  722. /* Get is_rep0_long bit */
  723. leal is_rep0_long(,%edx,2), %ebx
  724. call rc_bit
  725. jnz 98f
  726. movw $1, len(%ebp)
  727. movb $STATE_LIT_SHORTREP, %ch
  728. jmp 99f
  729. 1: /* Get is_rep1 bit */
  730. incb %cl
  731. leal is_rep1(,%edx,2), %ebx
  732. call rc_bit
  733. jz 98f
  734. /* Get is_rep2 bit */
  735. incb %cl
  736. leal is_rep2(,%edx,2), %ebx
  737. call rc_bit
  738. adcb $0, %cl
  739. 98: /* Decode length */
  740. movl $rep_len_dec, %ebx
  741. call lzma_len
  742. 99: /* Update LZMA state */
  743. cmpb $STATE_LIT_MAX, %dl
  744. movb %ch, %dl
  745. jbe 1f
  746. movb $STATE_NONLIT_REP, %dl
  747. 1: /* Tail call */
  748. jmp match_rep
  749. .size lzma_match, . - lzma_match
  750. /*****************************************************************************
  751. * Decode one LZMA symbol
  752. *
  753. * Parameters:
  754. * %ss:%ebp : LZMA parameter block
  755. * %ds:%esi : compressed input data pointer
  756. * %es:%edi : uncompressed output data pointer
  757. * %edx : LZMA state
  758. * Returns:
  759. * %ds:%esi : compressed input data pointer (possibly updated)
  760. * %es:%edi : uncompressed output data pointer (updated)
  761. * %edx : LZMA state
  762. * CF : end of payload marker found
  763. * Corrupts:
  764. * %eax
  765. * %ebx
  766. * %ecx
  767. *****************************************************************************
  768. */
  769. lzma_decode:
  770. /* Get is_match bit */
  771. leal is_match(,%edx,2), %ebx
  772. call rc_bit
  773. jz lzma_literal
  774. /* Get is_rep bit */
  775. leal is_rep(,%edx,2), %ebx
  776. call rc_bit
  777. jz lzma_match
  778. jmp lzma_rep_match
  779. .size lzma_decode, . - lzma_decode
  780. /****************************************************************************
  781. * Undo effect of branch-call-jump (BCJ) filter
  782. *
  783. * Parameters:
  784. * %es:%esi : start of uncompressed output data (note %es)
  785. * %es:%edi : end of uncompressed output data
  786. * Returns:
  787. * Corrupts:
  788. * %eax
  789. * %ebx
  790. * %ecx
  791. * %edx
  792. * %esi
  793. *****************************************************************************
  794. */
  795. bcj_filter:
  796. /* Store (negative) start of data in %edx */
  797. movl %esi, %edx
  798. negl %edx
  799. /* Calculate limit in %ecx */
  800. leal -5(%edi,%edx), %ecx
  801. 1: /* Calculate offset in %ebx */
  802. leal (%esi,%edx), %ebx
  803. /* Check for end of data */
  804. cmpl %ecx, %ebx
  805. ja 99f
  806. /* Check for an opcode which would be followed by a rel32 address */
  807. ADDR32 es lodsb
  808. andb $0xfe, %al
  809. cmpb $0xe8, %al
  810. jne 1b
  811. /* Get current jump target value in %eax */
  812. ADDR32 es lodsl
  813. /* Convert absolute addresses in the range [0,limit) back to
  814. * relative addresses in the range [-offset,limit-offset).
  815. */
  816. cmpl %ecx, %eax
  817. jae 2f
  818. subl %ebx,%es:-4(%esi)
  819. 2: /* Convert negative numbers in the range [-offset,0) back to
  820. * positive numbers in the range [limit-offset,limit).
  821. */
  822. notl %eax /* Range is now [0,offset) */
  823. cmpl %ebx, %eax
  824. jae 1b
  825. addl %ecx,%es:-4(%esi)
  826. jmp 1b
  827. 99: /* Return */
  828. ret
  829. .size bcj_filter, . - bcj_filter
  830. /****************************************************************************
  831. * decompress (real-mode or 16/32-bit protected-mode near call)
  832. *
  833. * Decompress data
  834. *
  835. * Parameters (passed via registers):
  836. * %ds:%esi : Start of compressed input data
  837. * %es:%edi : Start of output buffer
  838. * Returns:
  839. * %ds:%esi - End of compressed input data
  840. * %es:%edi - End of decompressed output data
  841. * All other registers are preserved
  842. *
  843. * NOTE: It would be possible to build a smaller version of the
  844. * decompression code for -DKEEP_IT_REAL by using 16-bit registers
  845. * where possible.
  846. ****************************************************************************
  847. */
  848. .globl decompress
  849. decompress:
  850. /* Preserve registers */
  851. pushl %eax
  852. pushl %ebx
  853. pushl %ecx
  854. pushl %edx
  855. pushl %ebp
  856. /* Allocate parameter block */
  857. subl $sizeof__lzma_dec, %esp
  858. movl %esp, %ebp
  859. /* Zero parameter block and set all probabilities to 0.5 */
  860. pushl %edi
  861. pushw %es
  862. pushw %ss
  863. popw %es
  864. movl %ebp, %edi
  865. xorl %eax, %eax
  866. movl $( sizeof__lzma_dec / 4 ), %ecx
  867. ADDR32 rep stosl
  868. leal probs(%ebp), %edi
  869. movw $( ( 1 << 11 ) / 2 ), %ax
  870. movl $( ( sizeof__lzma_dec - probs ) / 2 ), %ecx
  871. ADDR32 rep stosw
  872. popw %es
  873. popl %edi
  874. /* Initialise remaining parameters */
  875. movl %edi, out_start(%ebp)
  876. print_character $('\n')
  877. ADDR32 lodsb /* discard initial byte */
  878. print_hex_byte %al
  879. ADDR32 lodsl
  880. bswapl %eax
  881. print_hex_dword %eax
  882. print_character $('\n')
  883. movl %eax, rc_code(%ebp)
  884. decl rc_range(%ebp)
  885. movl $STATE_LIT_LIT, %edx
  886. 1: /* Decompress until we reach end of buffer */
  887. call lzma_decode
  888. jnc 1b
  889. call rc_normalise
  890. print_character $('\n')
  891. /* Undo BCJ filter */
  892. pushl %esi
  893. movl out_start(%ebp), %esi
  894. call bcj_filter
  895. popl %esi
  896. /* Restore registers and return */
  897. addl $sizeof__lzma_dec, %esp
  898. popl %ebp
  899. popl %edx
  900. popl %ecx
  901. popl %ebx
  902. popl %eax
  903. ret
  904. /* Specify minimum amount of stack space required */
  905. .globl _min_decompress_stack
  906. .equ _min_decompress_stack, ( sizeof__lzma_dec + 512 /* margin */ )