1 | /* Bcj2.c -- Converter for x86 code (BCJ2) |
2 | 2008-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 | |
33 | int 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 b2 = buf0[inPos]; |
71 | outBuf[outPos++] = b2; |
72 | if (IsJ(prevByte, b2)) |
73 | break; |
74 | inPos++; |
75 | prevByte = b2; |
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 | |