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