Subversion Repositories Kolibri OS

Rev

Rev 5728 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
5728 serge 1
/* Bcj2.c -- BCJ2 Decoder (Converter for x86 code)
2
2015-08-01 : 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;
5809 serge 42
 
5728 serge 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[p->state++ - BCJ2_DEC_STATE_ORIG_0];
65
      p->dest = dest + 1;
66
    }
67
  }
68
 
69
  /*
70
  if (BCJ2_IS_32BIT_STREAM(p->state))
71
  {
72
    const Byte *cur = p->bufs[p->state];
73
    if (cur == p->lims[p->state])
5809 serge 74
    return SZ_OK;
5728 serge 75
    p->bufs[p->state] = cur + 4;
76
 
77
    {
78
      UInt32 val;
79
      Byte *dest;
80
      SizeT rem;
81
 
82
      p->ip += 4;
83
      val = GetBe32(cur) - p->ip;
84
      dest = p->dest;
85
      rem = p->destLim - dest;
86
      if (rem < 4)
87
      {
88
        SizeT i;
89
        SetUi32(p->temp, val);
90
        for (i = 0; i < rem; i++)
91
          dest[i] = p->temp[i];
92
        p->dest = dest + rem;
93
        p->state = BCJ2_DEC_STATE_ORIG_0 + (unsigned)rem;
94
        return SZ_OK;
95
      }
96
      SetUi32(dest, val);
97
      p->temp[3] = (Byte)(val >> 24);
98
      p->dest = dest + 4;
99
      p->state = BCJ2_DEC_STATE_OK;
100
    }
101
  }
102
  */
103
 
104
  for (;;)
105
  {
106
    if (BCJ2_IS_32BIT_STREAM(p->state))
107
      p->state = BCJ2_DEC_STATE_OK;
108
    else
109
    {
110
      if (p->range < kTopValue)
111
      {
112
        if (p->bufs[BCJ2_STREAM_RC] == p->lims[BCJ2_STREAM_RC])
113
        {
114
          p->state = BCJ2_STREAM_RC;
115
          return SZ_OK;
116
        }
117
        p->range <<= 8;
118
        p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++;
119
      }
120
 
121
      {
122
        const Byte *src = p->bufs[BCJ2_STREAM_MAIN];
123
        const Byte *srcLim;
124
        Byte *dest;
125
        SizeT num = p->lims[BCJ2_STREAM_MAIN] - src;
126
 
127
        if (num == 0)
128
        {
129
          p->state = BCJ2_STREAM_MAIN;
130
          return SZ_OK;
131
        }
132
 
133
        dest = p->dest;
134
        if (num > (SizeT)(p->destLim - dest))
135
        {
136
          num = p->destLim - dest;
137
          if (num == 0)
138
          {
139
            p->state = BCJ2_DEC_STATE_ORIG;
140
            return SZ_OK;
141
          }
142
        }
143
 
144
        srcLim = src + num;
145
 
146
        if (p->temp[3] == 0x0F && (src[0] & 0xF0) == 0x80)
147
          *dest = src[0];
148
        else for (;;)
149
        {
150
          Byte b = *src;
151
          *dest = b;
152
          if (b != 0x0F)
5809 serge 153
    {
5728 serge 154
            if ((b & 0xFE) == 0xE8)
5809 serge 155
        break;
5728 serge 156
            dest++;
157
            if (++src != srcLim)
158
              continue;
159
            break;
160
          }
161
          dest++;
162
          if (++src == srcLim)
163
            break;
164
          if ((*src & 0xF0) != 0x80)
165
            continue;
166
          *dest = *src;
167
          break;
168
        }
169
 
170
        num = src - p->bufs[BCJ2_STREAM_MAIN];
171
 
172
        if (src == srcLim)
173
        {
174
          p->temp[3] = src[-1];
175
          p->bufs[BCJ2_STREAM_MAIN] = src;
176
          p->ip += (UInt32)num;
177
          p->dest += num;
178
          p->state =
179
            p->bufs[BCJ2_STREAM_MAIN] ==
180
            p->lims[BCJ2_STREAM_MAIN] ?
181
              (unsigned)BCJ2_STREAM_MAIN :
182
              (unsigned)BCJ2_DEC_STATE_ORIG;
183
          return SZ_OK;
5809 serge 184
    }
185
 
5728 serge 186
        {
187
          UInt32 bound, ttt;
188
          CProb *prob;
189
          Byte b = src[0];
190
          Byte prev = (Byte)(num == 0 ? p->temp[3] : src[-1]);
191
 
192
          p->temp[3] = b;
193
          p->bufs[BCJ2_STREAM_MAIN] = src + 1;
194
          num++;
195
          p->ip += (UInt32)num;
196
          p->dest += num;
5809 serge 197
 
5728 serge 198
          prob = p->probs + (unsigned)(b == 0xE8 ? 2 + (unsigned)prev : (b == 0xE9 ? 1 : 0));
5809 serge 199
 
5728 serge 200
          _IF_BIT_0
201
          {
202
            _UPDATE_0
203
            continue;
204
          }
205
          _UPDATE_1
5809 serge 206
 
207
    }
5728 serge 208
      }
209
    }
210
 
211
    {
212
      UInt32 val;
213
      unsigned cj = (p->temp[3] == 0xE8) ? BCJ2_STREAM_CALL : BCJ2_STREAM_JUMP;
214
      const Byte *cur = p->bufs[cj];
215
      Byte *dest;
216
      SizeT rem;
217
 
218
      if (cur == p->lims[cj])
219
      {
220
        p->state = cj;
221
        break;
222
      }
223
 
224
      val = GetBe32(cur);
225
      p->bufs[cj] = cur + 4;
226
 
227
      p->ip += 4;
228
      val -= p->ip;
229
      dest = p->dest;
230
      rem = p->destLim - dest;
231
 
232
      if (rem < 4)
233
      {
234
        SizeT i;
235
        SetUi32(p->temp, val);
236
        for (i = 0; i < rem; i++)
237
          dest[i] = p->temp[i];
238
        p->dest = dest + rem;
239
        p->state = BCJ2_DEC_STATE_ORIG_0 + (unsigned)rem;
240
        break;
241
      }
242
 
243
      SetUi32(dest, val);
244
      p->temp[3] = (Byte)(val >> 24);
245
      p->dest = dest + 4;
5809 serge 246
      }
5728 serge 247
    }
248
 
249
  if (p->range < kTopValue && p->bufs[BCJ2_STREAM_RC] != p->lims[BCJ2_STREAM_RC])
250
  {
251
    p->range <<= 8;
252
    p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++;
253
  }
254
 
255
  return SZ_OK;
256
}