rlm@1: /* Bra86.c -- Converter for x86 code (BCJ) rlm@1: 2008-10-04 : Igor Pavlov : Public domain */ rlm@1: rlm@1: #include "Bra.h" rlm@1: rlm@1: #define Test86MSByte(b) ((b) == 0 || (b) == 0xFF) rlm@1: rlm@1: const Byte kMaskToAllowedStatus[8] = {1, 1, 1, 0, 1, 0, 0, 0}; rlm@1: const Byte kMaskToBitNumber[8] = {0, 1, 2, 2, 3, 3, 3, 3}; rlm@1: rlm@1: SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding) rlm@1: { rlm@1: SizeT bufferPos = 0, prevPosT; rlm@1: UInt32 prevMask = *state & 0x7; rlm@1: if (size < 5) rlm@1: return 0; rlm@1: ip += 5; rlm@1: prevPosT = (SizeT)0 - 1; rlm@1: rlm@1: for (;;) rlm@1: { rlm@1: Byte *p = data + bufferPos; rlm@1: Byte *limit = data + size - 4; rlm@1: for (; p < limit; p++) rlm@1: if ((*p & 0xFE) == 0xE8) rlm@1: break; rlm@1: bufferPos = (SizeT)(p - data); rlm@1: if (p >= limit) rlm@1: break; rlm@1: prevPosT = bufferPos - prevPosT; rlm@1: if (prevPosT > 3) rlm@1: prevMask = 0; rlm@1: else rlm@1: { rlm@1: prevMask = (prevMask << ((int)prevPosT - 1)) & 0x7; rlm@1: if (prevMask != 0) rlm@1: { rlm@1: Byte b = p[4 - kMaskToBitNumber[prevMask]]; rlm@1: if (!kMaskToAllowedStatus[prevMask] || Test86MSByte(b)) rlm@1: { rlm@1: prevPosT = bufferPos; rlm@1: prevMask = ((prevMask << 1) & 0x7) | 1; rlm@1: bufferPos++; rlm@1: continue; rlm@1: } rlm@1: } rlm@1: } rlm@1: prevPosT = bufferPos; rlm@1: rlm@1: if (Test86MSByte(p[4])) rlm@1: { rlm@1: UInt32 src = ((UInt32)p[4] << 24) | ((UInt32)p[3] << 16) | ((UInt32)p[2] << 8) | ((UInt32)p[1]); rlm@1: UInt32 dest; rlm@1: for (;;) rlm@1: { rlm@1: Byte b; rlm@1: int index; rlm@1: if (encoding) rlm@1: dest = (ip + (UInt32)bufferPos) + src; rlm@1: else rlm@1: dest = src - (ip + (UInt32)bufferPos); rlm@1: if (prevMask == 0) rlm@1: break; rlm@1: index = kMaskToBitNumber[prevMask] * 8; rlm@1: b = (Byte)((dest >> (24 - index)) & 0xFF); rlm@1: if (!Test86MSByte(b)) rlm@1: break; rlm@1: src = dest ^ ((1 << (32 - index)) - 1); rlm@1: } rlm@1: p[4] = (Byte)((~(((dest >> 24) & 1) - 1)) & 0xFF); rlm@1: p[3] = (Byte)((dest >> 16) & 0xFF); rlm@1: p[2] = (Byte)((dest >> 8) & 0xFF); rlm@1: p[1] = (Byte)(dest & 0xFF); rlm@1: bufferPos += 5; rlm@1: } rlm@1: else rlm@1: { rlm@1: prevMask = ((prevMask << 1) & 0x7) | 1; rlm@1: bufferPos++; rlm@1: } rlm@1: } rlm@1: prevPosT = bufferPos - prevPosT; rlm@1: *state = ((prevPosT > 3) ? 0 : ((prevMask << ((int)prevPosT - 1)) & 0x7)); rlm@1: return bufferPos; rlm@1: }