[13350] | 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 | }
|
---|