1 /* Bcj2.c -- BCJ2 Decoder (Converter for x86 code)
\r
2 2021-02-09 : Igor Pavlov : Public domain */
\r
11 #define kTopValue ((UInt32)1 << 24)
\r
12 #define kNumModelBits 11
\r
13 #define kBitModelTotal (1 << kNumModelBits)
\r
14 #define kNumMoveBits 5
\r
16 #define _IF_BIT_0 ttt = *prob; bound = (p->range >> kNumModelBits) * ttt; if (p->code < bound)
\r
17 #define _UPDATE_0 p->range = bound; *prob = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));
\r
18 #define _UPDATE_1 p->range -= bound; p->code -= bound; *prob = (CProb)(ttt - (ttt >> kNumMoveBits));
\r
20 void Bcj2Dec_Init(CBcj2Dec *p)
\r
24 p->state = BCJ2_DEC_STATE_OK;
\r
29 for (i = 0; i < sizeof(p->probs) / sizeof(p->probs[0]); i++)
\r
30 p->probs[i] = kBitModelTotal >> 1;
\r
33 SRes Bcj2Dec_Decode(CBcj2Dec *p)
\r
37 p->state = BCJ2_DEC_STATE_OK;
\r
38 for (; p->range != 5; p->range++)
\r
40 if (p->range == 1 && p->code != 0)
\r
41 return SZ_ERROR_DATA;
\r
43 if (p->bufs[BCJ2_STREAM_RC] == p->lims[BCJ2_STREAM_RC])
\r
45 p->state = BCJ2_STREAM_RC;
\r
49 p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++;
\r
52 if (p->code == 0xFFFFFFFF)
\r
53 return SZ_ERROR_DATA;
\r
55 p->range = 0xFFFFFFFF;
\r
57 else if (p->state >= BCJ2_DEC_STATE_ORIG_0)
\r
59 while (p->state <= BCJ2_DEC_STATE_ORIG_3)
\r
61 Byte *dest = p->dest;
\r
62 if (dest == p->destLim)
\r
64 *dest = p->temp[(size_t)p->state - BCJ2_DEC_STATE_ORIG_0];
\r
71 if (BCJ2_IS_32BIT_STREAM(p->state))
\r
73 const Byte *cur = p->bufs[p->state];
\r
74 if (cur == p->lims[p->state])
\r
76 p->bufs[p->state] = cur + 4;
\r
84 val = GetBe32(cur) - p->ip;
\r
86 rem = p->destLim - dest;
\r
90 SetUi32(p->temp, val);
\r
91 for (i = 0; i < rem; i++)
\r
92 dest[i] = p->temp[i];
\r
93 p->dest = dest + rem;
\r
94 p->state = BCJ2_DEC_STATE_ORIG_0 + (unsigned)rem;
\r
98 p->temp[3] = (Byte)(val >> 24);
\r
100 p->state = BCJ2_DEC_STATE_OK;
\r
107 if (BCJ2_IS_32BIT_STREAM(p->state))
\r
108 p->state = BCJ2_DEC_STATE_OK;
\r
111 if (p->range < kTopValue)
\r
113 if (p->bufs[BCJ2_STREAM_RC] == p->lims[BCJ2_STREAM_RC])
\r
115 p->state = BCJ2_STREAM_RC;
\r
119 p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++;
\r
123 const Byte *src = p->bufs[BCJ2_STREAM_MAIN];
\r
124 const Byte *srcLim;
\r
126 SizeT num = (SizeT)(p->lims[BCJ2_STREAM_MAIN] - src);
\r
130 p->state = BCJ2_STREAM_MAIN;
\r
135 if (num > (SizeT)(p->destLim - dest))
\r
137 num = (SizeT)(p->destLim - dest);
\r
140 p->state = BCJ2_DEC_STATE_ORIG;
\r
145 srcLim = src + num;
\r
147 if (p->temp[3] == 0x0F && (src[0] & 0xF0) == 0x80)
\r
155 if ((b & 0xFE) == 0xE8)
\r
158 if (++src != srcLim)
\r
163 if (++src == srcLim)
\r
165 if ((*src & 0xF0) != 0x80)
\r
171 num = (SizeT)(src - p->bufs[BCJ2_STREAM_MAIN]);
\r
175 p->temp[3] = src[-1];
\r
176 p->bufs[BCJ2_STREAM_MAIN] = src;
\r
177 p->ip += (UInt32)num;
\r
180 p->bufs[BCJ2_STREAM_MAIN] ==
\r
181 p->lims[BCJ2_STREAM_MAIN] ?
\r
182 (unsigned)BCJ2_STREAM_MAIN :
\r
183 (unsigned)BCJ2_DEC_STATE_ORIG;
\r
191 Byte prev = (Byte)(num == 0 ? p->temp[3] : src[-1]);
\r
194 p->bufs[BCJ2_STREAM_MAIN] = src + 1;
\r
196 p->ip += (UInt32)num;
\r
199 prob = p->probs + (unsigned)(b == 0xE8 ? 2 + (unsigned)prev : (b == 0xE9 ? 1 : 0));
\r
214 unsigned cj = (p->temp[3] == 0xE8) ? BCJ2_STREAM_CALL : BCJ2_STREAM_JUMP;
\r
215 const Byte *cur = p->bufs[cj];
\r
219 if (cur == p->lims[cj])
\r
225 val = GetBe32(cur);
\r
226 p->bufs[cj] = cur + 4;
\r
231 rem = (SizeT)(p->destLim - dest);
\r
235 p->temp[0] = (Byte)val; if (rem > 0) dest[0] = (Byte)val; val >>= 8;
\r
236 p->temp[1] = (Byte)val; if (rem > 1) dest[1] = (Byte)val; val >>= 8;
\r
237 p->temp[2] = (Byte)val; if (rem > 2) dest[2] = (Byte)val; val >>= 8;
\r
238 p->temp[3] = (Byte)val;
\r
239 p->dest = dest + rem;
\r
240 p->state = BCJ2_DEC_STATE_ORIG_0 + (unsigned)rem;
\r
244 SetUi32(dest, val);
\r
245 p->temp[3] = (Byte)(val >> 24);
\r
246 p->dest = dest + 4;
\r
250 if (p->range < kTopValue && p->bufs[BCJ2_STREAM_RC] != p->lims[BCJ2_STREAM_RC])
\r
253 p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++;
\r