diff options
author | Igor Pavlov <87184205+ip7z@users.noreply.github.com> | 2021-12-27 00:00:00 +0000 |
---|---|---|
committer | Igor Pavlov <87184205+ip7z@users.noreply.github.com> | 2022-03-18 15:35:13 +0500 |
commit | f19f813537c7aea1c20749c914e756b54a9c3cf5 (patch) | |
tree | 816ba62ca7c0fa19f2eb46d9e9d6f7dd7c3a744d /C/Bcj2.c | |
parent | 98e06a519b63b81986abe76d28887f6984a7732b (diff) | |
download | 7zip-f19f813537c7aea1c20749c914e756b54a9c3cf5.tar.gz 7zip-f19f813537c7aea1c20749c914e756b54a9c3cf5.tar.bz2 7zip-f19f813537c7aea1c20749c914e756b54a9c3cf5.zip |
'21.07'21.07
Diffstat (limited to 'C/Bcj2.c')
-rw-r--r-- | C/Bcj2.c | 257 |
1 files changed, 257 insertions, 0 deletions
diff --git a/C/Bcj2.c b/C/Bcj2.c new file mode 100644 index 0000000..c7b9567 --- /dev/null +++ b/C/Bcj2.c | |||
@@ -0,0 +1,257 @@ | |||
1 | /* Bcj2.c -- BCJ2 Decoder (Converter for x86 code) | ||
2 | 2021-02-09 : Igor Pavlov : Public domain */ | ||
3 | |||
4 | #include "Precomp.h" | ||
5 | |||
6 | #include "Bcj2.h" | ||
7 | #include "CpuArch.h" | ||
8 | |||
9 | #define CProb UInt16 | ||
10 | |||
11 | #define kTopValue ((UInt32)1 << 24) | ||
12 | #define kNumModelBits 11 | ||
13 | #define kBitModelTotal (1 << kNumModelBits) | ||
14 | #define kNumMoveBits 5 | ||
15 | |||
16 | #define _IF_BIT_0 ttt = *prob; bound = (p->range >> kNumModelBits) * ttt; if (p->code < bound) | ||
17 | #define _UPDATE_0 p->range = bound; *prob = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); | ||
18 | #define _UPDATE_1 p->range -= bound; p->code -= bound; *prob = (CProb)(ttt - (ttt >> kNumMoveBits)); | ||
19 | |||
20 | void Bcj2Dec_Init(CBcj2Dec *p) | ||
21 | { | ||
22 | unsigned i; | ||
23 | |||
24 | p->state = BCJ2_DEC_STATE_OK; | ||
25 | p->ip = 0; | ||
26 | p->temp[3] = 0; | ||
27 | p->range = 0; | ||
28 | p->code = 0; | ||
29 | for (i = 0; i < sizeof(p->probs) / sizeof(p->probs[0]); i++) | ||
30 | p->probs[i] = kBitModelTotal >> 1; | ||
31 | } | ||
32 | |||
33 | SRes Bcj2Dec_Decode(CBcj2Dec *p) | ||
34 | { | ||
35 | if (p->range <= 5) | ||
36 | { | ||
37 | p->state = BCJ2_DEC_STATE_OK; | ||
38 | for (; p->range != 5; p->range++) | ||
39 | { | ||
40 | if (p->range == 1 && p->code != 0) | ||
41 | return SZ_ERROR_DATA; | ||
42 | |||
43 | if (p->bufs[BCJ2_STREAM_RC] == p->lims[BCJ2_STREAM_RC]) | ||
44 | { | ||
45 | p->state = BCJ2_STREAM_RC; | ||
46 | return SZ_OK; | ||
47 | } | ||
48 | |||
49 | p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++; | ||
50 | } | ||
51 | |||
52 | if (p->code == 0xFFFFFFFF) | ||
53 | return SZ_ERROR_DATA; | ||
54 | |||
55 | p->range = 0xFFFFFFFF; | ||
56 | } | ||
57 | else if (p->state >= BCJ2_DEC_STATE_ORIG_0) | ||
58 | { | ||
59 | while (p->state <= BCJ2_DEC_STATE_ORIG_3) | ||
60 | { | ||
61 | Byte *dest = p->dest; | ||
62 | if (dest == p->destLim) | ||
63 | return SZ_OK; | ||
64 | *dest = p->temp[(size_t)p->state - BCJ2_DEC_STATE_ORIG_0]; | ||
65 | p->state++; | ||
66 | p->dest = dest + 1; | ||
67 | } | ||
68 | } | ||
69 | |||
70 | /* | ||
71 | if (BCJ2_IS_32BIT_STREAM(p->state)) | ||
72 | { | ||
73 | const Byte *cur = p->bufs[p->state]; | ||
74 | if (cur == p->lims[p->state]) | ||
75 | return SZ_OK; | ||
76 | p->bufs[p->state] = cur + 4; | ||
77 | |||
78 | { | ||
79 | UInt32 val; | ||
80 | Byte *dest; | ||
81 | SizeT rem; | ||
82 | |||
83 | p->ip += 4; | ||
84 | val = GetBe32(cur) - p->ip; | ||
85 | dest = p->dest; | ||
86 | rem = p->destLim - dest; | ||
87 | if (rem < 4) | ||
88 | { | ||
89 | SizeT i; | ||
90 | SetUi32(p->temp, val); | ||
91 | for (i = 0; i < rem; i++) | ||
92 | dest[i] = p->temp[i]; | ||
93 | p->dest = dest + rem; | ||
94 | p->state = BCJ2_DEC_STATE_ORIG_0 + (unsigned)rem; | ||
95 | return SZ_OK; | ||
96 | } | ||
97 | SetUi32(dest, val); | ||
98 | p->temp[3] = (Byte)(val >> 24); | ||
99 | p->dest = dest + 4; | ||
100 | p->state = BCJ2_DEC_STATE_OK; | ||
101 | } | ||
102 | } | ||
103 | */ | ||
104 | |||
105 | for (;;) | ||
106 | { | ||
107 | if (BCJ2_IS_32BIT_STREAM(p->state)) | ||
108 | p->state = BCJ2_DEC_STATE_OK; | ||
109 | else | ||
110 | { | ||
111 | if (p->range < kTopValue) | ||
112 | { | ||
113 | if (p->bufs[BCJ2_STREAM_RC] == p->lims[BCJ2_STREAM_RC]) | ||
114 | { | ||
115 | p->state = BCJ2_STREAM_RC; | ||
116 | return SZ_OK; | ||
117 | } | ||
118 | p->range <<= 8; | ||
119 | p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++; | ||
120 | } | ||
121 | |||
122 | { | ||
123 | const Byte *src = p->bufs[BCJ2_STREAM_MAIN]; | ||
124 | const Byte *srcLim; | ||
125 | Byte *dest; | ||
126 | SizeT num = (SizeT)(p->lims[BCJ2_STREAM_MAIN] - src); | ||
127 | |||
128 | if (num == 0) | ||
129 | { | ||
130 | p->state = BCJ2_STREAM_MAIN; | ||
131 | return SZ_OK; | ||
132 | } | ||
133 | |||
134 | dest = p->dest; | ||
135 | if (num > (SizeT)(p->destLim - dest)) | ||
136 | { | ||
137 | num = (SizeT)(p->destLim - dest); | ||
138 | if (num == 0) | ||
139 | { | ||
140 | p->state = BCJ2_DEC_STATE_ORIG; | ||
141 | return SZ_OK; | ||
142 | } | ||
143 | } | ||
144 | |||
145 | srcLim = src + num; | ||
146 | |||
147 | if (p->temp[3] == 0x0F && (src[0] & 0xF0) == 0x80) | ||
148 | *dest = src[0]; | ||
149 | else for (;;) | ||
150 | { | ||
151 | Byte b = *src; | ||
152 | *dest = b; | ||
153 | if (b != 0x0F) | ||
154 | { | ||
155 | if ((b & 0xFE) == 0xE8) | ||
156 | break; | ||
157 | dest++; | ||
158 | if (++src != srcLim) | ||
159 | continue; | ||
160 | break; | ||
161 | } | ||
162 | dest++; | ||
163 | if (++src == srcLim) | ||
164 | break; | ||
165 | if ((*src & 0xF0) != 0x80) | ||
166 | continue; | ||
167 | *dest = *src; | ||
168 | break; | ||
169 | } | ||
170 | |||
171 | num = (SizeT)(src - p->bufs[BCJ2_STREAM_MAIN]); | ||
172 | |||
173 | if (src == srcLim) | ||
174 | { | ||
175 | p->temp[3] = src[-1]; | ||
176 | p->bufs[BCJ2_STREAM_MAIN] = src; | ||
177 | p->ip += (UInt32)num; | ||
178 | p->dest += num; | ||
179 | p->state = | ||
180 | p->bufs[BCJ2_STREAM_MAIN] == | ||
181 | p->lims[BCJ2_STREAM_MAIN] ? | ||
182 | (unsigned)BCJ2_STREAM_MAIN : | ||
183 | (unsigned)BCJ2_DEC_STATE_ORIG; | ||
184 | return SZ_OK; | ||
185 | } | ||
186 | |||
187 | { | ||
188 | UInt32 bound, ttt; | ||
189 | CProb *prob; | ||
190 | Byte b = src[0]; | ||
191 | Byte prev = (Byte)(num == 0 ? p->temp[3] : src[-1]); | ||
192 | |||
193 | p->temp[3] = b; | ||
194 | p->bufs[BCJ2_STREAM_MAIN] = src + 1; | ||
195 | num++; | ||
196 | p->ip += (UInt32)num; | ||
197 | p->dest += num; | ||
198 | |||
199 | prob = p->probs + (unsigned)(b == 0xE8 ? 2 + (unsigned)prev : (b == 0xE9 ? 1 : 0)); | ||
200 | |||
201 | _IF_BIT_0 | ||
202 | { | ||
203 | _UPDATE_0 | ||
204 | continue; | ||
205 | } | ||
206 | _UPDATE_1 | ||
207 | |||
208 | } | ||
209 | } | ||
210 | } | ||
211 | |||
212 | { | ||
213 | UInt32 val; | ||
214 | unsigned cj = (p->temp[3] == 0xE8) ? BCJ2_STREAM_CALL : BCJ2_STREAM_JUMP; | ||
215 | const Byte *cur = p->bufs[cj]; | ||
216 | Byte *dest; | ||
217 | SizeT rem; | ||
218 | |||
219 | if (cur == p->lims[cj]) | ||
220 | { | ||
221 | p->state = cj; | ||
222 | break; | ||
223 | } | ||
224 | |||
225 | val = GetBe32(cur); | ||
226 | p->bufs[cj] = cur + 4; | ||
227 | |||
228 | p->ip += 4; | ||
229 | val -= p->ip; | ||
230 | dest = p->dest; | ||
231 | rem = (SizeT)(p->destLim - dest); | ||
232 | |||
233 | if (rem < 4) | ||
234 | { | ||
235 | p->temp[0] = (Byte)val; if (rem > 0) dest[0] = (Byte)val; val >>= 8; | ||
236 | p->temp[1] = (Byte)val; if (rem > 1) dest[1] = (Byte)val; val >>= 8; | ||
237 | p->temp[2] = (Byte)val; if (rem > 2) dest[2] = (Byte)val; val >>= 8; | ||
238 | p->temp[3] = (Byte)val; | ||
239 | p->dest = dest + rem; | ||
240 | p->state = BCJ2_DEC_STATE_ORIG_0 + (unsigned)rem; | ||
241 | break; | ||
242 | } | ||
243 | |||
244 | SetUi32(dest, val); | ||
245 | p->temp[3] = (Byte)(val >> 24); | ||
246 | p->dest = dest + 4; | ||
247 | } | ||
248 | } | ||
249 | |||
250 | if (p->range < kTopValue && p->bufs[BCJ2_STREAM_RC] != p->lims[BCJ2_STREAM_RC]) | ||
251 | { | ||
252 | p->range <<= 8; | ||
253 | p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++; | ||
254 | } | ||
255 | |||
256 | return SZ_OK; | ||
257 | } | ||