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