Home | History | Annotate | Download | only in C
      1 /* Bra86.c -- Converter for x86 code (BCJ)
      2 2013-11-12 : Igor Pavlov : Public domain */
      3 
      4 #include "Precomp.h"
      5 
      6 #include "Bra.h"
      7 
      8 #define Test86MSByte(b) ((((b) + 1) & 0xFE) == 0)
      9 
     10 SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding)
     11 {
     12   SizeT pos = 0;
     13   UInt32 mask = *state & 7;
     14   if (size < 5)
     15     return 0;
     16   size -= 4;
     17   ip += 5;
     18 
     19   for (;;)
     20   {
     21     Byte *p = data + pos;
     22     const Byte *limit = data + size;
     23     for (; p < limit; p++)
     24       if ((*p & 0xFE) == 0xE8)
     25         break;
     26 
     27     {
     28       SizeT d = (SizeT)(p - data - pos);
     29       pos = (SizeT)(p - data);
     30       if (p >= limit)
     31       {
     32         *state = (d > 2 ? 0 : mask >> (unsigned)d);
     33         return pos;
     34       }
     35       if (d > 2)
     36         mask = 0;
     37       else
     38       {
     39         mask >>= (unsigned)d;
     40         if (mask != 0 && (mask > 4 || mask == 3 || Test86MSByte(p[(mask >> 1) + 1])))
     41         {
     42           mask = (mask >> 1) | 4;
     43           pos++;
     44           continue;
     45         }
     46       }
     47     }
     48 
     49     if (Test86MSByte(p[4]))
     50     {
     51       UInt32 v = ((UInt32)p[4] << 24) | ((UInt32)p[3] << 16) | ((UInt32)p[2] << 8) | ((UInt32)p[1]);
     52       UInt32 cur = ip + (UInt32)pos;
     53       pos += 5;
     54       if (encoding)
     55         v += cur;
     56       else
     57         v -= cur;
     58       if (mask != 0)
     59       {
     60         unsigned sh = (mask & 6) << 2;
     61         if (Test86MSByte((Byte)(v >> sh)))
     62         {
     63           v ^= (((UInt32)0x100 << sh) - 1);
     64           if (encoding)
     65             v += cur;
     66           else
     67             v -= cur;
     68         }
     69         mask = 0;
     70       }
     71       p[1] = (Byte)v;
     72       p[2] = (Byte)(v >> 8);
     73       p[3] = (Byte)(v >> 16);
     74       p[4] = (Byte)(0 - ((v >> 24) & 1));
     75     }
     76     else
     77     {
     78       mask = (mask >> 1) | 4;
     79       pos++;
     80     }
     81   }
     82 }
     83