1 /*
2  * BCJ filter for x86 instructions
3  *
4  * Authors: Lasse Collin <lasse.collin@tukaani.org>
5  *          Igor Pavlov <http://7-zip.org/>
6  *
7  * This file has been put into the public domain.
8  * You can do whatever you want with this file.
9  */
10 
11 package org.tukaani.xz.simple;
12 
13 public final class X86 implements SimpleFilter {
14     private static final boolean[] MASK_TO_ALLOWED_STATUS
15             = {true, true, true, false, true, false, false, false};
16 
17     private static final int[] MASK_TO_BIT_NUMBER = {0, 1, 2, 2, 3, 3, 3, 3};
18 
19     private final boolean isEncoder;
20     private int pos;
21     private int prevMask = 0;
22 
test86MSByte(byte b)23     private static boolean test86MSByte(byte b) {
24         int i = b & 0xFF;
25         return i == 0x00 || i == 0xFF;
26     }
27 
X86(boolean isEncoder, int startPos)28     public X86(boolean isEncoder, int startPos) {
29         this.isEncoder = isEncoder;
30         pos = startPos + 5;
31     }
32 
code(byte[] buf, int off, int len)33     public int code(byte[] buf, int off, int len) {
34         int prevPos = off - 1;
35         int end = off + len - 5;
36         int i;
37 
38         for (i = off; i <= end; ++i) {
39             if ((buf[i] & 0xFE) != 0xE8)
40                 continue;
41 
42             prevPos = i - prevPos;
43             if ((prevPos & ~3) != 0) { // (unsigned)prevPos > 3
44                 prevMask = 0;
45             } else {
46                 prevMask = (prevMask << (prevPos - 1)) & 7;
47                 if (prevMask != 0) {
48                     if (!MASK_TO_ALLOWED_STATUS[prevMask] || test86MSByte(
49                             buf[i + 4 - MASK_TO_BIT_NUMBER[prevMask]])) {
50                         prevPos = i;
51                         prevMask = (prevMask << 1) | 1;
52                         continue;
53                     }
54                 }
55             }
56 
57             prevPos = i;
58 
59             if (test86MSByte(buf[i + 4])) {
60                 int src = (buf[i + 1] & 0xFF)
61                           | ((buf[i + 2] & 0xFF) << 8)
62                           | ((buf[i + 3] & 0xFF) << 16)
63                           | ((buf[i + 4] & 0xFF) << 24);
64                 int dest;
65                 while (true) {
66                     if (isEncoder)
67                         dest = src + (pos + i - off);
68                     else
69                         dest = src - (pos + i - off);
70 
71                     if (prevMask == 0)
72                         break;
73 
74                     int index = MASK_TO_BIT_NUMBER[prevMask] * 8;
75                     if (!test86MSByte((byte)(dest >>> (24 - index))))
76                         break;
77 
78                     src = dest ^ ((1 << (32 - index)) - 1);
79                 }
80 
81                 buf[i + 1] = (byte)dest;
82                 buf[i + 2] = (byte)(dest >>> 8);
83                 buf[i + 3] = (byte)(dest >>> 16);
84                 buf[i + 4] = (byte)(~(((dest >>> 24) & 1) - 1));
85                 i += 4;
86             } else {
87                 prevMask = (prevMask << 1) | 1;
88             }
89         }
90 
91         prevPos = i - prevPos;
92         prevMask = ((prevPos & ~3) != 0) ? 0 : prevMask << (prevPos - 1);
93 
94         i -= off;
95         pos += i;
96         return i;
97     }
98 }
99