src/third-party/lzma/Bra86.c (view raw)
1/* Bra86.c -- Converter for x86 code (BCJ)
22013-11-12 : Igor Pavlov : Public domain */
3
4#include "Precomp.h"
5
6#include "Bra.h"
7
8#define Test86MSByte(b) ((((b) + 1) & 0xFE) == 0)
9
10SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding)
11{
12 SizeT pos = 0;
13 UInt32 mask = *state & 7;
14 if (size < 5)
15 return 0;
16 size -= 4;
17 ip += 5;
18
19 for (;;)
20 {
21 Byte *p = data + pos;
22 const Byte *limit = data + size;
23 for (; p < limit; p++)
24 if ((*p & 0xFE) == 0xE8)
25 break;
26
27 {
28 SizeT d = (SizeT)(p - data - pos);
29 pos = (SizeT)(p - data);
30 if (p >= limit)
31 {
32 *state = (d > 2 ? 0 : mask >> (unsigned)d);
33 return pos;
34 }
35 if (d > 2)
36 mask = 0;
37 else
38 {
39 mask >>= (unsigned)d;
40 if (mask != 0 && (mask > 4 || mask == 3 || Test86MSByte(p[(mask >> 1) + 1])))
41 {
42 mask = (mask >> 1) | 4;
43 pos++;
44 continue;
45 }
46 }
47 }
48
49 if (Test86MSByte(p[4]))
50 {
51 UInt32 v = ((UInt32)p[4] << 24) | ((UInt32)p[3] << 16) | ((UInt32)p[2] << 8) | ((UInt32)p[1]);
52 UInt32 cur = ip + (UInt32)pos;
53 pos += 5;
54 if (encoding)
55 v += cur;
56 else
57 v -= cur;
58 if (mask != 0)
59 {
60 unsigned sh = (mask & 6) << 2;
61 if (Test86MSByte((Byte)(v >> sh)))
62 {
63 v ^= (((UInt32)0x100 << sh) - 1);
64 if (encoding)
65 v += cur;
66 else
67 v -= cur;
68 }
69 mask = 0;
70 }
71 p[1] = (Byte)v;
72 p[2] = (Byte)(v >> 8);
73 p[3] = (Byte)(v >> 16);
74 p[4] = (Byte)(0 - ((v >> 24) & 1));
75 }
76 else
77 {
78 mask = (mask >> 1) | 4;
79 pos++;
80 }
81 }
82}