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}
83