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