1 /* Bra86.c -- Converter for x86 code (BCJ)
2 2017-04-03 : Igor Pavlov : Public domain */
3 
4 #include "Precomp.h"
5 
6 #include "Bra.h"
7 
8 #define Test86MSByte(b) ((((b) + 1) & 0xFE) == 0)
9 
x86_Convert(Byte * data,SizeT size,UInt32 ip,UInt32 * state,int encoding)10 SizeT 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[(size_t)(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 }
83