wok-tiny view linux/stuff/unlzsa1.S @ rev 174

Up linux 2.6.20 (avoid 386 & 486 problems)
author Pascal Bellard <pascal.bellard@slitaz.org>
date Wed Jul 14 14:20:00 2021 +0000 (2021-07-14)
parents
children d5c772484b59
line source
1 // based on
2 // decompress_small.S - space-efficient decompressor implementation for 8088
3 //
4 // Copyright (C) 2019 Emmanuel Marty
5 //
6 // This software is provided 'as-is', without any express or implied
7 // warranty. In no event will the authors be held liable for any damages
8 // arising from the use of this software.
9 //
10 // Permission is granted to anyone to use this software for any purpose,
11 // including commercial applications, and to alter it and redistribute it
12 // freely, subject to the following restrictions:
13 //
14 // 1. The origin of this software must not be misrepresented; you must not
15 // claim that you wrote the original software. If you use this software
16 // in a product, an acknowledgment in the product documentation would be
17 // appreciated but is not required.
18 // 2. Altered source versions must be plainly marked as such, and must not be
19 // misrepresented as being the original software.
20 // 3. This notice may not be removed or altered from any source distribution.
22 // ---------------------------------------------------------------------------
23 // Decompress raw LZSA1 block
24 // inputs:
25 // * %ds:%si: raw LZSA1 block
26 // * %es:%di: output buffer
27 // ---------------------------------------------------------------------------
29 .code16
30 lzsa1_decompress:
31 //pushw %di // remember decompression offset
32 //cld // make string operations (lods, movs, stos..) move forward
34 lzsa1_decode_token:
35 xorb %ah, %ah // clear %ah
36 lodsb // read token byte: O|LLL|MMMM
37 movw %ax,%bx // keep token in %bl
39 andb $0x70, %al // isolate literals length in token (LLL)
40 je lzsa1_check_offset_size // if LLL=0, we have no literals; goto match
41 #ifdef ONLY8086
42 movb $4, %cl
43 shrb %cl, %al // shift literals length into place
44 #else
45 shrb $4, %al // shift literals length into place
46 #endif
48 cmpb $7, %al // LITERALS_RUN_LEN?
49 jne lzsa1_got_literals // no, we have the full literals count from the token, go copy
51 lodsb // grab extra length byte
52 addb $7, %al // add LITERALS_RUN_LEN
53 jnc lzsa1_got_literals // if no overflow, we have the full literals count, go copy
54 je lzsa1_big_literals
56 movb $1, %ah // add 256 (I'd prefer 'xchgb %al, %ah' max 1791 instead of 511)
57 lodsb // grab single extra length byte
58 .byte 0x3C // mask lodsw with cmpb $0xAD, %al
59 // (*like jmp short lzsa1_got_literals but faster)
61 lzsa1_big_literals:
62 lodsw // grab 16-bit extra length
64 lzsa1_got_literals:
65 xchgw %ax, %cx
66 #ifdef USE_MOVSW
67 shrw $1, %cx
68 rep movsw
69 adcw %cx, %cx
70 #endif
71 rep movsb // copy %cx literals from %ds:%si to %es:%di
73 lzsa1_check_offset_size:
74 testb %bl, %bl // check match offset size in token (O bit)
75 js lzsa1_get_long_offset
77 decw %cx
78 xchgw %ax, %cx // %ah to 0xff - %cx was zero from the rep movsb above
79 lodsb
80 .byte 0x3C // mask lodsw with cmpb $0xAD, %al
81 // (*like jmp short lzsa1_get_match_length but faster)
83 lzsa1_get_long_offset:
84 lodsw // Get 2-byte match offset
86 lzsa1_get_match_length:
87 xchgw %ax, %bx // %bx: match offset %ax: original token
88 andb $0xF, %al // isolate match length in token (MMMM)
89 addb $3, %al // add MIN_MATCH_SIZE
91 cmpb $0x12, %al // MATCH_RUN_LEN?
92 jne lzsa1_got_matchlen // no, we have the full match length from the token, go copy
94 lodsb // grab extra length byte
95 addb $0x12, %al // add MIN_MATCH_SIZE + MATCH_RUN_LEN
96 jnc lzsa1_got_matchlen // if no overflow, we have the entire length
97 je lzsa1_big_matchlen
99 movb $1, %ah // add 256 (I'd prefer 'xchgb %al, %ah' max 3071 instead of 511)
100 lodsb // grab single extra length byte
101 .byte 0x3C // mask lodsw with cmpb $0xAD, %al
102 // (*like jmp short lzsa1_got_matchlen but faster)
103 lzsa1_big_matchlen:
104 lodsw // grab 16-bit length
106 lzsa1_got_matchlen:
107 xchgw %ax, %cx // copy match length into %cx
108 jcxz lzsa1_done_decompressing // bail if we hit EOD
109 xchgw %ax, %si // save %si (current pointer to compressed data)
110 leaw (%bx,%di), %si // %es:%si now points at back reference in output data
111 #ifdef USE_MOVSW
112 cmpw $-2, %bx
113 jae lzsa1_store
114 shrw $1, %cx
115 rep movsw %es:(%si), %es:(%di)
116 adcw %cx, %cx
117 #endif
118 rep movsb %es:(%si), %es:(%di) // copy match
119 xchgw %ax, %si // restore %ds:%si
120 jmp lzsa1_decode_token // go decode another token
121 #ifdef USE_MOVSW
122 lzsa1_store:
123 je lzsa1_store_word
124 lodsb %es:(%si)
125 movb %al, %ah
126 .byte 0x3D // mask lodsw with cmpb $0x26AD, %ax
127 // (*like jmp short lzsa1_store_byte but faster)
128 lzsa1_store_word:
129 lodsw %es:(%si)
130 lzsa1_store_byte:
131 shrw $1, %cx
132 rep stosw
133 adcw %cx, %cx
134 rep stosb
135 xchgw %ax, %si // restore %ds:%si
136 jmp lzsa1_decode_token // go decode another token
137 #endif
139 lzsa1_done_decompressing:
140 // popw %ax // retrieve the original decompression offset
141 // xchgw %ax, %di // compute decompressed size
142 // subw %di, %ax
143 ret // done