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