1/* Bcj2.c -- Converter for x86 code (BCJ2)
22008-10-04 : Igor Pavlov : Public domain */
3
4#include "Bcj2.h"
5
6#ifdef _LZMA_PROB32
7#define CProb UInt32
8#else
9#define CProb UInt16
10#endif
11
12#define IsJcc(b0, b1) ((b0) == 0x0F && ((b1) & 0xF0) == 0x80)
13#define IsJ(b0, b1) ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1))
14
15#define kNumTopBits 24
16#define kTopValue ((UInt32)1 << kNumTopBits)
17
18#define kNumBitModelTotalBits 11
19#define kBitModelTotal (1 << kNumBitModelTotalBits)
20#define kNumMoveBits 5
21
22#define RC_READ_BYTE (*buffer++)
23#define RC_TEST { if (buffer == bufferLim) return SZ_ERROR_DATA; }
24#define RC_INIT2 code = 0; range = 0xFFFFFFFF; \
25  { int i; for (i = 0; i < 5; i++) { RC_TEST; code = (code << 8) | RC_READ_BYTE; }}
26
27#define NORMALIZE if (range < kTopValue) { RC_TEST; range <<= 8; code = (code << 8) | RC_READ_BYTE; }
28
29#define IF_BIT_0(p) ttt = *(p); bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
30#define UPDATE_0(p) range = bound; *(p) = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); NORMALIZE;
31#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CProb)(ttt - (ttt >> kNumMoveBits)); NORMALIZE;
32
33int Bcj2_Decode(
34    const Byte *buf0, SizeT size0,
35    const Byte *buf1, SizeT size1,
36    const Byte *buf2, SizeT size2,
37    const Byte *buf3, SizeT size3,
38    Byte *outBuf, SizeT outSize)
39{
40  CProb p[256 + 2];
41  SizeT inPos = 0, outPos = 0;
42
43  const Byte *buffer, *bufferLim;
44  UInt32 range, code;
45  Byte prevByte = 0;
46
47  unsigned int i;
48  for (i = 0; i < sizeof(p) / sizeof(p[0]); i++)
49    p[i] = kBitModelTotal >> 1;
50
51  buffer = buf3;
52  bufferLim = buffer + size3;
53  RC_INIT2
54
55  if (outSize == 0)
56    return SZ_OK;
57
58  for (;;)
59  {
60    Byte b;
61    CProb *prob;
62    UInt32 bound;
63    UInt32 ttt;
64
65    SizeT limit = size0 - inPos;
66    if (outSize - outPos < limit)
67      limit = outSize - outPos;
68    while (limit != 0)
69    {
70      Byte b = buf0[inPos];
71      outBuf[outPos++] = b;
72      if (IsJ(prevByte, b))
73        break;
74      inPos++;
75      prevByte = b;
76      limit--;
77    }
78
79    if (limit == 0 || outPos == outSize)
80      break;
81
82    b = buf0[inPos++];
83
84    if (b == 0xE8)
85      prob = p + prevByte;
86    else if (b == 0xE9)
87      prob = p + 256;
88    else
89      prob = p + 257;
90
91    IF_BIT_0(prob)
92    {
93      UPDATE_0(prob)
94      prevByte = b;
95    }
96    else
97    {
98      UInt32 dest;
99      const Byte *v;
100      UPDATE_1(prob)
101      if (b == 0xE8)
102      {
103        v = buf1;
104        if (size1 < 4)
105          return SZ_ERROR_DATA;
106        buf1 += 4;
107        size1 -= 4;
108      }
109      else
110      {
111        v = buf2;
112        if (size2 < 4)
113          return SZ_ERROR_DATA;
114        buf2 += 4;
115        size2 -= 4;
116      }
117      dest = (((UInt32)v[0] << 24) | ((UInt32)v[1] << 16) |
118          ((UInt32)v[2] << 8) | ((UInt32)v[3])) - ((UInt32)outPos + 4);
119      outBuf[outPos++] = (Byte)dest;
120      if (outPos == outSize)
121        break;
122      outBuf[outPos++] = (Byte)(dest >> 8);
123      if (outPos == outSize)
124        break;
125      outBuf[outPos++] = (Byte)(dest >> 16);
126      if (outPos == outSize)
127        break;
128      outBuf[outPos++] = prevByte = (Byte)(dest >> 24);
129    }
130  }
131  return (outPos == outSize) ? SZ_OK : SZ_ERROR_DATA;
132}
133