Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

unlzma.S 23KB

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