15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Bra86.c -- Converter for x86 code (BCJ) 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)2008-10-04 : Igor Pavlov : Public domain */ 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "Bra.h" 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define Test86MSByte(b) ((b) == 0 || (b) == 0xFF) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const Byte kMaskToAllowedStatus[8] = {1, 1, 1, 0, 1, 0, 0, 0}; 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const Byte kMaskToBitNumber[8] = {0, 1, 2, 2, 3, 3, 3, 3}; 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding) 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SizeT bufferPos = 0, prevPosT; 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UInt32 prevMask = *state & 0x7; 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (size < 5) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ip += 5; 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prevPosT = (SizeT)0 - 1; 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (;;) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Byte *p = data + bufferPos; 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Byte *limit = data + size - 4; 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (; p < limit; p++) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((*p & 0xFE) == 0xE8) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bufferPos = (SizeT)(p - data); 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (p >= limit) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prevPosT = bufferPos - prevPosT; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (prevPosT > 3) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prevMask = 0; 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prevMask = (prevMask << ((int)prevPosT - 1)) & 0x7; 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (prevMask != 0) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Byte b = p[4 - kMaskToBitNumber[prevMask]]; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!kMaskToAllowedStatus[prevMask] || Test86MSByte(b)) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prevPosT = bufferPos; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prevMask = ((prevMask << 1) & 0x7) | 1; 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bufferPos++; 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prevPosT = bufferPos; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (Test86MSByte(p[4])) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UInt32 src = ((UInt32)p[4] << 24) | ((UInt32)p[3] << 16) | ((UInt32)p[2] << 8) | ((UInt32)p[1]); 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UInt32 dest; 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (;;) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Byte b; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int index; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (encoding) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest = (ip + (UInt32)bufferPos) + src; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest = src - (ip + (UInt32)bufferPos); 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (prevMask == 0) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index = kMaskToBitNumber[prevMask] * 8; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) b = (Byte)(dest >> (24 - index)); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!Test86MSByte(b)) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) src = dest ^ ((1 << (32 - index)) - 1); 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p[4] = (Byte)(~(((dest >> 24) & 1) - 1)); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p[3] = (Byte)(dest >> 16); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p[2] = (Byte)(dest >> 8); 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p[1] = (Byte)dest; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bufferPos += 5; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prevMask = ((prevMask << 1) & 0x7) | 1; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bufferPos++; 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prevPosT = bufferPos - prevPosT; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *state = ((prevPosT > 3) ? 0 : ((prevMask << ((int)prevPosT - 1)) & 0x7)); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return bufferPos; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 86