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 |
|
---|
23 | private static boolean test86MSByte(byte b) {
|
---|
24 | int i = b & 0xFF;
|
---|
25 | return i == 0x00 || i == 0xFF;
|
---|
26 | }
|
---|
27 |
|
---|
28 | public X86(boolean isEncoder, int startPos) {
|
---|
29 | this.isEncoder = isEncoder;
|
---|
30 | pos = startPos + 5;
|
---|
31 | }
|
---|
32 |
|
---|
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 | }
|
---|